授权
接下来跟着源码来一起学习授权相关知识。
一般的service注入服务方式有如下:
builder.Services.AddAuthorization(option =>
{
//增加授权策略
option.AddPolicy("Api1", builder =>
{
builder.RequireAuthenticatedUser();
builder.RequireClaim("scope", "api1");
builder.AddRequirements(new CustomAuthorizationRequirement("Policy01");
});
});
这里来一起查看AddAuthorization做了什么事?
源码AddAuthorization路径(aspnetcore/src/Security/Authorization/Policy/src/PolicyServiceCollectionExtensions.cs)。
AddAuthorizationCore注册了AuthorizationOptions配置项内容,此内容会在之后的DefaultAuthorizationPolicyProvider类GetPolicyAsync调用其AuthorizationOptions自身的GetPolicyTask(policyName)方法获取以下AddPolicy配置内容(通过PolicyMap)。
AddAuthorization内的option()=>{},是对AuthorizationOptions进行的配置。看一下具体配置内容。
大致看代码,就是通过AuthorizationPolicyBuilder配置完成后,build()生成AuthorizationPolicy保存在本身的字典内。
这里讲解具体配置方法具体含义
/*
在类型为List<IAuthorizationRequirement>()的Requirements中
新增"拒绝匿名访问"即为DenyAnonymousAuthorizationRequirement。
DenyAnonymousAuthorizationRequirement的操作HandleRequirementAsync
方法中判断当前用户身份是否存在以及是否认证,如果是,
则在AuthorizationHandlerContext上下文内设置_succeedCalled=true,
_pendingRequirements.Remove(requirement);//移除当前DenyAnonymousAuthorizationRequirement
*/
builder.RequireAuthenticatedUser();
——————————————————————————————————————————————————————————————————————————————————————
/*
在类型为List<IAuthorizationRequirement>()的Requirements中
新增new ClaimsAuthorizationRequirement("scope", "api1")。
ClaimsAuthorizationRequirement的操作HandleRequirementAsync
方法中判断当前用户身份是否存在给定的ClaimType(此处为"scope"),如果是,
则在AuthorizationHandlerContext上下文内设置_succeedCalled=true,
_pendingRequirements.Remove(requirement);//移除当前ClaimsAuthorizationRequirement
*/
builder.RequireClaim("scope", "api1");
——————————————————————————————————————————————————————————————————————————————————————
/*
向Requirements添加自定义IAuthorizationRequirement内容,
此处自定义类为CustomAuthorizationRequirement
*/
builder.AddRequirements(new CustomAuthorizationRequirement("Policy01");
——————————————————————————————————————————————————————————————————————————————————————
AddAuthorizationCore()方法注册一些服务项。
AddAuthorizationPolicyEvaluator()同样注册了一些服务项。
至此,AddAuthorization()的内容都了解了,无非是注册了一些服务项,没有额外的其他。
接下来看授权使用,一般的写法如下所示
app.UseAuthorization()
UseAuthorization,路径(aspnetcore/src/Security/Authorization/Policy/src/AuthorizationAppBuilderExtensions.cs)
查看关键代码,AuthorizationMiddleware。
1、context.GetEndPoint()获取EndPointRoutingMiddleware中间选择的终结点,通过endPoint.MetaData获取对应action方法上标注的所有特性(其中AuthorizeAttribute继承自IAuthorizeData)。
2、AuthorizationPolicy.CombineAsync整合IAuthorizeData,AuthorizationPolicy和IAuthorizationRequirementData的数据内容生成完整AuthorizationPolicy(整合内容:Requirements和AuthenticationSchemes,其中Requirements中包含角色roles)。
3、IPolicyEvaluator.AuthenticateAsync(policy, context)验证认证。
4、IPolicyEvaluator.AuthorizeAsync(policy, authenticateResult!, context, resource)验证授权。
其中,_authorization为DefaultAuthorizationService,涉及到调用AuthorizationServiceExtensions(路径:aspnetcore/src/Security/Authorization/Core/src/AuthorizationServiceExtensions.cs)
认证核心代码为DefaultAuthorizationService(路径:aspnetcore/src/Security/Authorization/Core/src/DefaultAuthorizationService.cs):
①_contextFactory.CreateContext,获取认证处理上下文。
②_handlers.GetHandlersAsync,最终获取到PassThroughAuthorizationHandler。
③handler.HandleAsync,获取所有的Requirements,调用他们自身的HandleAsync方法进行处理。此处自带或者自定义的Requirement都必须继承AuthorizationHandler<>泛型方法,重写HandleRequirementAsync进行逻辑处理。
重写范例如下DenyAnonymousAuthorizationRequirement:
自此,net6授权过程的全部源代码讲完了,核心处理就在AuthorizationOption中配置的Requirement中,一张图结束本节内容。