【问题标题】:.NET Core Bypass or turn off [Authorize(Roles="")] during local development.NET Core 本地开发时绕过或关闭[Authorize(Roles="")]
【发布时间】: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 属性?

【问题讨论】:

  • 在启动代码中放置一个标志,如果处于开发模式,则不应用身份验证管道。

标签: c# asp.net-core .net-core asp.net-core-webapi asp.net-core-3.1


【解决方案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
                });
    

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2020-10-28
      • 2023-02-02
      • 1970-01-01
      • 2021-01-11
      • 2019-11-02
      • 2014-10-08
      • 2021-06-09
      • 2010-10-07
      相关资源
      最近更新 更多