ASP.NET Core 实现自定义认证
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET Core 实现自定义认证相关的知识,希望对你有一定的参考价值。
前言
在 ASP.NET Core 中,我们常使用基于 JWT 的认证:
services.AddAuthentication(option =>
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
).AddJwtBearer(options =>
options.TokenValidationParameters = new TokenValidationParameters
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["JwtToken:Issuer"],
ValidAudience = Configuration["JwtToken:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtToken:SecretKey"]))
;
);
但有时候,我们需要使用自定义认证,比如使用QueryString(htttp://xxx?_key=xxx),只要请求中包含的_key
的值正确即可。
AddJwtBearer 实现原理
为了实现自定义认证,我们决定仿照AddJwtBearer
的实现机制。
AddJwtBearer
实际执行的是AddScheme
方法:
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<JwtBearerOptions> configureOptions)
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, JwtBearerPostConfigureOptions>());
return builder.AddScheme<JwtBearerOptions, JwtBearerHandler>(authenticationScheme, displayName, configureOptions);
JwtBearerHandler
是具体的处理程序,继承自AuthenticationHandler<TOptions>
,主要代码在HandleAuthenticateAsync
内:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
...
if (string.IsNullOrEmpty(token))
string authorization = Request.Headers.Authorization.ToString();
// If no authorization header found, nothing to process further
if (string.IsNullOrEmpty(authorization))
return AuthenticateResult.NoResult();
if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
token = authorization.Substring("Bearer ".Length).Trim();
// If no token found, no further work possible
if (string.IsNullOrEmpty(token))
return AuthenticateResult.NoResult();
...
foreach (var validator in Options.SecurityTokenValidators)
if (validator.CanReadToken(token))
...
var tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options)
Principal = principal,
SecurityToken = validatedToken
;
...
tokenValidatedContext.Success();
return tokenValidatedContext.Result!;
...
从Request.Headers.Authorization
获取token,然后用Options.SecurityTokenValidators
验证token合法后,返回结果。
Demo
DemoAuthenticationOptions
创建DemoAuthenticationOptions
,继承自AuthenticationSchemeOptions
:
public class DemoAuthenticationOptions : AuthenticationSchemeOptions
public const string Scheme = "Demo";
DemoAuthenticationHandler
创建DemoAuthenticationHandler
,继承自AuthenticationHandler<DemoAuthenticationOptions>
:
public class DemoAuthenticationHandler : AuthenticationHandler<DemoAuthenticationOptions>
public DemoAuthenticationHandler(IOptionsMonitor<DemoAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
throw new NotImplementedException();
实现 HandleAuthenticateAsync 方法
从请求的Query
中获取key
,然后检查是否合法:
protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
if (!Request.Query.TryGetValue("_key", out var keys))
return AuthenticateResult.NoResult();
var key = keys.FirstOrDefault();
//到数据库检索
if (key =="123456")
var claims = new List<Claim>
new Claim(ClaimTypes.Name, "My IO")
;
var identity = new ClaimsIdentity(claims, DemoAuthenticationOptions.Scheme);
var identities = new List<ClaimsIdentity> identity ;
var principal = new ClaimsPrincipal(identities);
var ticket = new AuthenticationTicket(principal, DemoAuthenticationOptions.Scheme);
return AuthenticateResult.Success(ticket);
return AuthenticateResult.NoResult();
定义扩展方法
定义扩展方法,使用我们上面创建的DemoAuthenticationHandler
:
public static class AuthenticationBuilderExtensions
public static AuthenticationBuilder AddDemoAuthentication(this AuthenticationBuilder authenticationBuilder, Action<DemoAuthenticationOptions> options)
return authenticationBuilder.AddScheme<DemoAuthenticationOptions, DemoAuthenticationHandler>(DemoAuthenticationOptions.Scheme, options);
使用
修改Startup.cs:
services.AddAuthentication(option =>
option.DefaultAuthenticateScheme = DemoAuthenticationOptions.Scheme;
option.DefaultChallengeScheme = DemoAuthenticationOptions.Scheme;
)
.AddDemoAuthentication(options => );
结论
当不加Query
或使用错误的key
时,返回401 认证失败:
仅当使用正确的key
时,API 访问成功:
想了解更多内容,请关注我的个人公众号”My IO“
以上是关于ASP.NET Core 实现自定义认证的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT)