上一篇分析了权限检验的过程,但感觉还没有分析透彻,今天继续:
IPolicyEvaluator的默认实现类PolicyEvaluator,它有两个方法:
1、AuthenticateAsync,判断身份
2、AuthorizeAsync,判断权限
A、PolicyEvaluator.AuthenticateAsync
研究AuthenticateAsync,通过它的方法定义(如下),可以判断出,身份信息在哪里,在HttpContext中。
public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
继续看代码如下,在context中调用AuthenticateAsync,它是HttpContext的一个扩展方法,定义在AuthenticationHttpContextExtensions中。
var result = await context.AuthenticateAsync(scheme);
B、HttpContext.AuthenticateAsync(位于AuthenticationHttpContextExtensions)
继续查看代码如下,可以看到它通过获取IAuthenticationService的实现类来执行AuthenticateAsync方法。IAuthenticationService默认实现类是AuthenticationService(位于Http文件夹下)
GetAuthenticationService(context).AuthenticateAsync(context, scheme);
private static IAuthenticationService GetAuthenticationService(HttpContext context) =>
context.RequestServices.GetService<IAuthenticationService>()
C、AuthenticationService(位于Http文件夹下)
AuthenticationService,它的构造函数如下,使用了IAuthenticationHandlerProvider类
public AuthenticationService(IAuthenticationSchemeProvider schemes, IAuthenticationHandlerProvider handlers, IClaimsTransformation transform, IOptions<AuthenticationOptions> options)
继续深挖,看AuthenticateAsync方法,关键代码如下,通过IAuthenticationHandlerProvider获得IAuthenticationHandler,之后执行其AuthenticateAsync,获得身份验证结果。
IAuthenticationHandlerProvider的默认实现类是AuthenticationHandlerProvider。
IAuthenticationHandler有很多实现类,其中CookieAuthenticationHandler是Cookie身份验证方案的默认实现类
var handler = await Handlers.GetHandlerAsync(context, scheme);
var result = (await handler.AuthenticateAsync()) ?? AuthenticateResult.NoResult();
D、AuthenticationHandlerProvider.GetHandlerAsync(位于Http文件夹下)
这里个关键代码如下,获取对应Handler的实例;如果没有,则创建一个新的。
var handler = (context.RequestServices.GetService(scheme.HandlerType) ??
ActivatorUtilities.CreateInstance(context.RequestServices, scheme.HandlerType))
as IAuthenticationHandler;
E、CookieAuthenticationHandler,位于Cookie文件夹下
这里就基于Cookie来验证身份。
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var result = await EnsureCookieTicket();
if (!result.Succeeded)
{
return result;
}
// We check this before the ValidatePrincipal event because we want to make sure we capture a clean clone
// without picking up any per-request modifications to the principal.
await CheckForRefreshAsync(result.Ticket);
Debug.Assert(result.Ticket != null);
var context = new CookieValidatePrincipalContext(Context, Scheme, Options, result.Ticket);
await Events.ValidatePrincipal(context);
if (context.Principal == null)
{
return AuthenticateResult.Fail("No principal.");
}
if (context.ShouldRenew)
{
RequestRefresh(result.Ticket, context.Principal);
}
return AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
}
所以,如果要创建一套新的身份验证方案,那么对应的是
1、首先必须是基于Web的,身份信息将存储在HttpContext中
2、实现IAuthenticationHandler接口,处理多个场景
其他则看具体身份验证要求来实现。
梳理完之后,可以发现,PolicyEvaluator.AuthenticateAsync 和 AuthenticationMiddleware.Invoke,在功能上来说,是几乎一致的。