# 使用多重认证架构(Mutliple Authentication Schemes)
原文:ASP.NET Core - Using Mutliple Authentication Schemes (opens new window)
参考文档:
在某些情况下,你可能想让控制器方法具有多种认证方式。比如:我既想通过 Identity Server 来鉴权,也想通过自定义的方法来鉴权(最终需要两者都验证通过或者某一项验证通过才行)。要想实现这点,就需要创建自己的 AuthenticationScheme、自定义 schema(类似JwtBearer)以及配置一个 Policy。
Tips: 最终是需要都验证通过,还是某一个验证通过就可以?
# 自定义 AuthenticationScheme
创建一个自定义的 authentication scheme,它将服务于标记了 [Authorize] 特性的控制器方法。
为了创建一个自定义的 authentication scheme,你需要定义以下内容,
- CustomAuthenticationDefaults
- CustomAuthenticationHandler
- CustomAuthenticationOptions
首先,定义 CustomAuthenticationDefaults
public static class CustomAuthenticationDefaults
{
public const string AuthenticationScheme = "Custom";
}
然后 AuthenticationSchemeOptions,该类充当的角色类似配置
using Microsoft.AspNetCore.Authentication;
public class CustomAuthOptions : AuthenticationSchemeOptions
{
public string UserInfoEndpoint { get; set; }
}
定义自定义认证逻辑 CustomAuthenticationHandler (opens new window)
在 ConfigureServices 方法中注册该服务 services.AddCustomAuthentication(Configuration);
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{
// Identity Server Configuration
var identityUrl = configuration.GetValue<string>("Authentication:IdentityServerBaseUrl");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "your_api";
});
// Custom Authentication configuration
services.AddAuthentication(CustomAuthenticationDefaults.AuthenticationScheme)
.AddScheme<CustomAuthOptions, CustomAuthenticationHandler>(CustomAuthenticationDefaults.AuthenticationScheme,
o => o.UserInfoEndpoint = configuration.GetValue<string>("Authentication:Custom:UserInfoEndpoint"));
// we define policies here where we configure which scheme or combinations we need for each of our policies.
services.AddAuthorization(options =>
{
// authorize using custom auth scheme only
options.AddPolicy("UserRole", policy =>
{
policy.AuthenticationSchemes.Add(CustomAuthenticationDefaults.AuthenticationScheme);
policy.RequireRole("User");
});
// authorize using custom auth scheme as well as identity server
options.AddPolicy("OrdersWrite", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.AuthenticationSchemes.Add(CustomAuthenticationDefaults.AuthenticationScheme);
policy.RequireClaim("scope", "orders:write");
});
});
return services;
}
接下来是如何使用该验证逻辑,在控制器方法上增加特性
[Authorize(Policy = "OrdersWrite")]
public async Task<ActionResult<OrderResult>> CreateOrder(OrderRequest orderRequest)
{
var clientIdClaim = HttpContext.User.FindFirst("client_id"); // identity server client
var userIdClaim = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier); // user authenticated using custom auth handler.
...
}
现在,我们就可以在Http请求头中加入身份标识来请求资源了
Authorization: <type> <credentials>
Identity Server 的
Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
自定义的
Authorization: custom abcasdjasdjlaksdjlasjdlasjd