.NET Core 本地开发时绕过或关闭[Authorize(Roles="")]

Posted

技术标签:

【中文标题】.NET Core 本地开发时绕过或关闭[Authorize(Roles="")]【英文标题】:.NET Core Bypass or turn off [Authorize(Roles="")] during local development 【发布时间】:2022-01-02 07:07:46 【问题描述】:

我有以下代码可以绕过在本地开发期间添加身份验证,我正在使用 Azure AD 和 .NET Core。

#if !DEBUG
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
               .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));
#endif

但是由于我的控制器受 Authorize 属性保护,我如何在本地开发期间绕过 Controller 内的 Authorize 属性:

[Authorize(Roles = "Buyer")]
public class ProductController : ApiBaseController


在 .NET Framework 中,我有以下代码来覆盖 Authorize 属性:

public class MyAuthorizeAttribute : AuthorizeAttribute
    
     #if DEBUG
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        
            return true;
        
     #endif
    

.NET Core 的等效代码是什么?还是有其他方法可以覆盖 Startup.cs 类中的 Authorize 属性?

【问题讨论】:

在启动代码中放置一个标志,如果处于开发模式,则不应用身份验证管道。 【参考方案1】:

我认为您可以为此使用IClaimsTransformation。在这种情况下,我只会为每个人添加一个角色,但是当它连接起来时,它只会在你处于开发阶段时才会这样做(注意:你需要确保环境变量设置正确,所以IsDevelopment工作)。

AddRolesClaimsTransformation.cs
/// <summary>
/// Adds roles to a user on the fly, this will hard code a Buyer role for everyone.
/// </summary>
public class AddRolesClaimsTransformation : IClaimsTransformation

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    
        // Clone current identity
        var clone = principal.Clone();
        var ident = (ClaimsIdentity)clone.Identity;

        ident.AddClaim(new Claim(ClaimTypes.Role, "Buyer"));

        return clone;
    

Startup.cs
// Only in dev
if (builder.Environment.IsDevelopment())

    builder.Services.AddScoped<IClaimsTransformation, AddRolesClaimsTransformation>();

根据 Microsoft 文档,这应该适用于 ASP.NET Core 3.1。但是,我针对 .NET 6 对其进行了测试(在 .NET 6 中,新站点的模板将 Startup.cs 内容移动到 Program.cs)。

另一方面,如果您依赖WebHostEnvironment 上的IsDevelopment 管道,则不必使用编译器指令。这样,一旦设置了环境,它就可以正常工作,但是您将其部署到那里(例如,意外的 Debug 构建不可能使其进入不应该在的环境中)。

【讨论】:

【参考方案2】:

您可以使用[Authorize(Policy... 添加一个间接层,而不是使用[Authorize(Roles... 明确指定每个控制器所需的角色。

这样您就可以在您的StartUp 类(或IConfigureOptions&lt;AuthorizationOptions&gt; 服务)中决定每个策略的确切含义。包括您可能有的任何其他奇怪的要求。

[Authorize(Policy= "Buyer")]
public class ProductController : ApiBaseController

...

services.AddAuthorization(o =>

    o.AddPolicy("Buyer", b => 
#if DEBUG
        b.RequireAuthenticatedUser();
#else
        b.RequireRole("Buyer");
#endif
    );
);

【讨论】:

Nvm 我明白了,谢谢【参考方案3】:

感谢 Jeremy 的正确指导,我使用下面的代码让它工作了:

在控制器类中我使用了基于策略的授权:

 [Authorize(Policy= "Buyer")]
 public class ProductController : ApiBaseController
 
 

在start.cs中我们可以根据DEBUG条件添加认证和授权:

#if !DEBUG
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
               .AddMicrosoftIdentityWebApi(config.GetSection("AzureAd"));
#endif

            services.AddAuthorization(options =>
            
                // policy for read access
                options.AddPolicy("Buyer", policy =>
                
#if DEBUG
                    policy.RequireAuthenticatedUser();
#else
                    policy.RequireRole("Buyer");
#endif
                );
            );

对于调试模式下的 RequireAuthenticatedUser(),我们使用以下代码在所有控制器上添加 AllowAnonymous 属性:

app.UseEndpoints(endpoints =>
            
#if DEBUG
                endpoints.MapControllers().WithMetadata(new AllowAnonymousAttribute());
#else
                    endpoints.MapControllers();
#endif
            );

【讨论】:

以上是关于.NET Core 本地开发时绕过或关闭[Authorize(Roles="")]的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP .NET Core 3.1 中调用 LoggerExtensions 方法时禁用/关闭 FxCop CA1303

在 AZURE 或本地部署 .net core 3.0

选项卡关闭控制绕过验证 .NET

.Net Core Web API,如果角色或策略匹配,则授权操作

ASP.net Core 2.0 AzureAd Bearer JWT-Token Auth 在验证签名时不会失败

在 ASP.NET Core 2 中处理异常的推荐方法? [关闭]