.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<AuthorizationOptions>
服务)中决定每个策略的确切含义。包括您可能有的任何其他奇怪的要求。
[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
.Net Core Web API,如果角色或策略匹配,则授权操作