.NET Core 在本地开发期间绕过或关闭 [Authorize(Roles="")]
.NET Core Bypass or turn off [Authorize(Roles="")] during local development
我有以下代码可以在本地开发期间绕过添加身份验证,我使用的是 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 class 中的 Authorize 属性?
我认为你可以使用 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
管道,则不必使用编译器指令。这样,一旦设置了环境,无论您将其部署到那里,它都可以正常工作(例如,意外的调试构建不可能进入它不应该在的环境中)。
无需使用 [Authorize(Roles...
明确指定每个控制器所需的角色,您可以使用 [Authorize(Policy...
添加一个间接层。
这样您就可以在 StartUp
class(或 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
});
});
感谢 Jeremy 的正确指导,我使用以下代码让它工作:
在控制器中 class 我使用了基于策略的授权:
[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
});
我有以下代码可以在本地开发期间绕过添加身份验证,我使用的是 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 class 中的 Authorize 属性?
我认为你可以使用 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
管道,则不必使用编译器指令。这样,一旦设置了环境,无论您将其部署到那里,它都可以正常工作(例如,意外的调试构建不可能进入它不应该在的环境中)。
无需使用 [Authorize(Roles...
明确指定每个控制器所需的角色,您可以使用 [Authorize(Policy...
添加一个间接层。
这样您就可以在 StartUp
class(或 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
});
});
感谢 Jeremy 的正确指导,我使用以下代码让它工作:
在控制器中 class 我使用了基于策略的授权:
[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
});