回顾:认证受权方案之受权初识html
从上一节中,咱们在对受权系统已经有了初步的认识和使用,能够发现,asp.net core为咱们提供的受权策略是一个很是强大丰富且灵活的认证受权方案,可以知足大部分的受权场景。git
在ConfigureServices中配置服务:将受权服务添加到容器github
public void ConfigureServices(IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("customizePermisson", policy => policy .Requirements .Add(new PermissionRequirement("user"))); }); //此外,还须要在 IAuthorizationHandler 类型的范围内向 DI 系统注册新的处理程序: services.AddScoped<IAuthorizationHandler, PermissionRequirementHandler>(); }
在Configure中注册管道:运行使用调用方法来配置Http请求管道c#
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { //开启受权 app.UseAuthorization(); }
经过以上几行代码的实现,就能够进行受权了,这个时候,你能够会问,这几行代码都进行了什么操做实现受权的?数组
好了,继续回到上节最后说的在这一节中对受权策略的核心进行一步步的揭秘的。
app
引入总体结构框架
添加受权策略服务使用AddAuthorization
方法,以便调用。asp.net
从源码能够发现,从core3.0后,由以前在core2.0中的AuthorizationServiceCollectionExtensions.cs
文件中,原来的AddAuthorization
的方法变为了AddAuthorizationCore
方法,微软在这一块进行了封装在PolicyServiceCollectionExtensions.cs
文件中,沿用了以前AddAuthorization
拓展名称,不影响以前版本的使用。async
咱们来看看aspnetcore源码:ide
public static class PolicyServiceCollectionExtensions { public static IServiceCollection AddAuthorizationPolicyEvaluator(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.TryAddSingleton<AuthorizationPolicyMarkerService>(); services.TryAddTransient<IPolicyEvaluator, PolicyEvaluator>(); services.TryAddTransient<IAuthorizationMiddlewareResultHandler, AuthorizationMiddlewareResultHandler>(); return services; } public static IServiceCollection AddAuthorization(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.AddAuthorizationCore(); services.AddAuthorizationPolicyEvaluator(); return services; } public static IServiceCollection AddAuthorization(this IServiceCollection services, Action<AuthorizationOptions> configure) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.AddAuthorizationCore(configure); services.AddAuthorizationPolicyEvaluator(); return services; } }
public static class AuthorizationServiceCollectionExtensions { public static IServiceCollection AddAuthorizationCore(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.TryAdd(ServiceDescriptor.Transient<IAuthorizationService, DefaultAuthorizationService>()); services.TryAdd(ServiceDescriptor.Transient<IAuthorizationPolicyProvider, DefaultAuthorizationPolicyProvider>()); services.TryAdd(ServiceDescriptor.Transient<IAuthorizationHandlerProvider, DefaultAuthorizationHandlerProvider>()); services.TryAdd(ServiceDescriptor.Transient<IAuthorizationEvaluator, DefaultAuthorizationEvaluator>()); services.TryAdd(ServiceDescriptor.Transient<IAuthorizationHandlerContextFactory, DefaultAuthorizationHandlerContextFactory>()); services.TryAddEnumerable(ServiceDescriptor.Transient<IAuthorizationHandler, PassThroughAuthorizationHandler>()); return services; } public static IServiceCollection AddAuthorizationCore(this IServiceCollection services, Action<AuthorizationOptions> configure) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.Configure(configure); return services.AddAuthorizationCore(); } }
由上可知,在调用AddAuthorization
方法进行受权配置的时候,须要使用到AuthorizationOptions
委托方式传参。
因此咱们再来看看下面这一行代码,经过AddPolicy
实现添加策略方式。
options.AddPolicy("customizePermisson",policy => policy.Requirements.Add(new PermissionRequirement("user")));
查看源码发现是引用了AuthorizationOptions
对象。
受权选项实现添加和受权配置,提供受权服务的配置。
源码以下:
public class AuthorizationOptions { private Dictionary<string, AuthorizationPolicy> PolicyMap { get; } = new Dictionary<string, AuthorizationPolicy>(StringComparer.OrdinalIgnoreCase); public bool InvokeHandlersAfterFailure { get; set; } = true; public AuthorizationPolicy DefaultPolicy { get; set; } = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); public AuthorizationPolicy? FallbackPolicy { get; set; } public void AddPolicy(string name, AuthorizationPolicy policy) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } PolicyMap[name] = policy; } public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (configurePolicy == null) { throw new ArgumentNullException(nameof(configurePolicy)); } var policyBuilder = new AuthorizationPolicyBuilder(); configurePolicy(policyBuilder); PolicyMap[name] = policyBuilder.Build(); } public AuthorizationPolicy GetPolicy(string name) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (PolicyMap.TryGetValue(name, out var value)) { return value; } return null; } }
定义一个字典
private Dictionary<string, AuthorizationPolicy> PolicyMap { get; } = new Dictionary<string, AuthorizationPolicy>(StringComparer.OrdinalIgnoreCase);
目的在于将定义的受权策略方式都保存在这个声明的PolicyMap
当中,而其中AddPolicy
方法是将配置的策略添加到字典中。
public void AddPolicy(string name, AuthorizationPolicy policy);
public void AddPolicy(string name, Action<AuthorizationPolicyBuilder> configurePolicy);
而这方法中涉及到两种不一样的传参对象AuthorizationPolicy
和AuthorizationPolicyBuilder
。
表示受权要求和方案的集合。具体源码以下:
public class AuthorizationPolicy { public AuthorizationPolicy(IEnumerable<IAuthorizationRequirement> requirements, IEnumerable<string> authenticationSchemes) { if (requirements == null) { throw new ArgumentNullException(nameof(requirements)); } if (authenticationSchemes == null) { throw new ArgumentNullException(nameof(authenticationSchemes)); } if (requirements.Count() == 0) { throw new InvalidOperationException(Resources.Exception_AuthorizationPolicyEmpty); } Requirements = new List<IAuthorizationRequirement>(requirements).AsReadOnly(); AuthenticationSchemes = new List<string>(authenticationSchemes).AsReadOnly(); } public IReadOnlyList<IAuthorizationRequirement> Requirements { get; } public IReadOnlyList<string> AuthenticationSchemes { get; } public static AuthorizationPolicy Combine(params AuthorizationPolicy[] policies) { if (policies == null) { throw new ArgumentNullException(nameof(policies)); } return Combine((IEnumerable<AuthorizationPolicy>)policies); } public static AuthorizationPolicy Combine(IEnumerable<AuthorizationPolicy> policies) { if (policies == null) { throw new ArgumentNullException(nameof(policies)); } var builder = new AuthorizationPolicyBuilder(); foreach (var policy in policies) { builder.Combine(policy); } return builder.Build(); } public static async Task<AuthorizationPolicy> CombineAsync(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authorizeData) { if (policyProvider == null) { throw new ArgumentNullException(nameof(policyProvider)); } if (authorizeData == null) { throw new ArgumentNullException(nameof(authorizeData)); } // Avoid allocating enumerator if the data is known to be empty var skipEnumeratingData = false; if (authorizeData is IList<IAuthorizeData> dataList) { skipEnumeratingData = dataList.Count == 0; } AuthorizationPolicyBuilder policyBuilder = null; if (!skipEnumeratingData) { foreach (var authorizeDatum in authorizeData) { if (policyBuilder == null) { policyBuilder = new AuthorizationPolicyBuilder(); } var useDefaultPolicy = true; if (!string.IsNullOrWhiteSpace(authorizeDatum.Policy)) { var policy = await policyProvider.GetPolicyAsync(authorizeDatum.Policy); if (policy == null) { throw new InvalidOperationException(Resources.FormatException_AuthorizationPolicyNotFound(authorizeDatum.Policy)); } policyBuilder.Combine(policy); useDefaultPolicy = false; } var rolesSplit = authorizeDatum.Roles?.Split(','); if (rolesSplit != null && rolesSplit.Any()) { var trimmedRolesSplit = rolesSplit.Where(r => !string.IsNullOrWhiteSpace(r)).Select(r => r.Trim()); policyBuilder.RequireRole(trimmedRolesSplit); useDefaultPolicy = false; } var authTypesSplit = authorizeDatum.AuthenticationSchemes?.Split(','); if (authTypesSplit != null && authTypesSplit.Any()) { foreach (var authType in authTypesSplit) { if (!string.IsNullOrWhiteSpace(authType)) { policyBuilder.AuthenticationSchemes.Add(authType.Trim()); } } } if (useDefaultPolicy) { policyBuilder.Combine(await policyProvider.GetDefaultPolicyAsync()); } } } // If we have no policy by now, use the fallback policy if we have one if (policyBuilder == null) { var fallbackPolicy = await policyProvider.GetFallbackPolicyAsync(); if (fallbackPolicy != null) { return fallbackPolicy; } } return policyBuilder?.Build(); } }
咱们从源码中能够发现,Authorization
对象 Combine
方法目的在于将受权策略进行合并,同时调用了AuthorizationPolicyBuilder
对象中Combine
方法,对受权方案或者受权策略进行合并。再来看看AuthorizationPolicy
对象中的CombineAsync
方法,这里的参数用到了IAuthorizeData
,同时这个方法的过程是将可能基于角色,基于方案或者基于策略都合并转换为是受权策略的方式,也是经过调用AuthorizationPolicyBuilder
对象来实现合并。 因此能够看得出AuthorizationPolicyBuilder
提供了一些建立AuthorizationPolicy
的方法。
这个时候,咱们能够发现,其实以前说的基于角色、基于方案的受权方式本质上来讲都是基于策略受权。
除了上面说到使用AuthorizationPolicy
对象以外,咱们还能够用AuthorizationPolicyBuilder
对象以Buider
来建立AuthorizationPolicy
对象,将多个AuthorizationPolicy
对象提供的数组进行合并,因此AuthorizationPolicyBuilder
提供的Combine
方法的使用,为AuthorizationPolicy
受权构建提供了许多便捷的方式。
public class AuthorizationPolicyBuilder { public AuthorizationPolicyBuilder(params string[] authenticationSchemes) { AddAuthenticationSchemes(authenticationSchemes); } public AuthorizationPolicyBuilder(AuthorizationPolicy policy) { Combine(policy); } public IList<IAuthorizationRequirement> Requirements { get; set; } = new List<IAuthorizationRequirement>(); public IList<string> AuthenticationSchemes { get; set; } = new List<string>(); public AuthorizationPolicyBuilder AddAuthenticationSchemes(params string[] schemes) { foreach (var authType in schemes) { AuthenticationSchemes.Add(authType); } return this; } public AuthorizationPolicyBuilder AddRequirements(params IAuthorizationRequirement[] requirements) { foreach (var req in requirements) { Requirements.Add(req); } return this; } public AuthorizationPolicyBuilder Combine(AuthorizationPolicy policy) { if (policy == null) { throw new ArgumentNullException(nameof(policy)); } AddAuthenticationSchemes(policy.AuthenticationSchemes.ToArray()); AddRequirements(policy.Requirements.ToArray()); return this; } public AuthorizationPolicyBuilder RequireClaim(string claimType, params string[] allowedValues) { if (claimType == null) { throw new ArgumentNullException(nameof(claimType)); } return RequireClaim(claimType, (IEnumerable<string>)allowedValues); } public AuthorizationPolicyBuilder RequireClaim(string claimType, IEnumerable<string> allowedValues) { if (claimType == null) { throw new ArgumentNullException(nameof(claimType)); } Requirements.Add(new ClaimsAuthorizationRequirement(claimType, allowedValues)); return this; } public AuthorizationPolicyBuilder RequireClaim(string claimType) { if (claimType == null) { throw new ArgumentNullException(nameof(claimType)); } Requirements.Add(new ClaimsAuthorizationRequirement(claimType, allowedValues: null)); return this; } public AuthorizationPolicyBuilder RequireRole(params string[] roles) { if (roles == null) { throw new ArgumentNullException(nameof(roles)); } return RequireRole((IEnumerable<string>)roles); } public AuthorizationPolicyBuilder RequireRole(IEnumerable<string> roles) { if (roles == null) { throw new ArgumentNullException(nameof(roles)); } Requirements.Add(new RolesAuthorizationRequirement(roles)); return this; } public AuthorizationPolicyBuilder RequireUserName(string userName) { if (userName == null) { throw new ArgumentNullException(nameof(userName)); } Requirements.Add(new NameAuthorizationRequirement(userName)); return this; } public AuthorizationPolicyBuilder RequireAuthenticatedUser() { Requirements.Add(new DenyAnonymousAuthorizationRequirement()); return this; } public AuthorizationPolicyBuilder RequireAssertion(Func<AuthorizationHandlerContext, bool> handler) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Requirements.Add(new AssertionRequirement(handler)); return this; } public AuthorizationPolicyBuilder RequireAssertion(Func<AuthorizationHandlerContext, Task<bool>> handler) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Requirements.Add(new AssertionRequirement(handler)); return this; } public AuthorizationPolicy Build() { return new AuthorizationPolicy(Requirements, AuthenticationSchemes.Distinct()); } }
由上面多出出现的IAuthorizationRequirement
对象能够发现,受权要求Requirement
属性是策略的核心方案,每一种Requirement
都表明一种受权方式。同时IAuthorizationPolicyBuilder
为这些预约义的方案建立了它们对应的使用方式并将其添加到Requirements
集合中。
public interface IAuthorizationRequirement { }
接口并无任何实现成员,由于受权要求是具备不一样的表现形式的,全部才没有具体的实现成员。受权要求目的在于检验某个当前用户是否具备相应的要求, 因此大部分IAuthorizationRequirement
接口的实现类都继承了IAuthorizationHandler
接口来提供HandleAsync方法来实现对应的受权检验。
下面介绍asp.net core框架里面默认实现的几种IAuthorizationRequirement
实现类型。
阻止匿名用户操做,言外之意就是拒绝未被验证的匿名用户访问资源。
源码以下:
public class DenyAnonymousAuthorizationRequirement : AuthorizationHandler<DenyAnonymousAuthorizationRequirement>, IAuthorizationRequirement { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DenyAnonymousAuthorizationRequirement requirement) { var user = context.User; var userIsAnonymous = user?.Identity == null || !user.Identities.Any(i => i.IsAuthenticated); if (!userIsAnonymous) { context.Succeed(requirement); } return Task.CompletedTask; } }
经过用户的CliamPrincipal
对象身份是否为空或是不是一个通过认证的用户身份,以此来肯定当前请求的用户是否来源于匿名用户。
指定用户名的受权方式,判断当前用户与某个指定的用户是否匹配以此来受权访问资源。
源码以下:
public class NameAuthorizationRequirement : AuthorizationHandler<NameAuthorizationRequirement>, IAuthorizationRequirement { public NameAuthorizationRequirement(string requiredName) { if (requiredName == null) { throw new ArgumentNullException(nameof(requiredName)); } RequiredName = requiredName; } public string RequiredName { get; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, NameAuthorizationRequirement requirement) { if (context.User != null) { if (context.User.Identities.Any(i => string.Equals(i.Name, requirement.RequiredName))) { context.Succeed(requirement); } } return Task.CompletedTask; } }
其中RequiredName
属性为受权用户,经过HandleRequirementAsync
方法进行校验当前用户的ClaimPrincipal
对象的身份与RequiredName
是否具备匹配。
这里的判断用的是 string.Equals() 说明这里比较的用户名是区别大小写的。
基于指定声明类型的受权策略,检验当前用户是否声明类型和候选值。
源码以下:
public class ClaimsAuthorizationRequirement : AuthorizationHandler<ClaimsAuthorizationRequirement>, IAuthorizationRequirement { public ClaimsAuthorizationRequirement(string claimType, IEnumerable<string> allowedValues) { if (claimType == null) { throw new ArgumentNullException(nameof(claimType)); } ClaimType = claimType; AllowedValues = allowedValues; } public string ClaimType { get; } public IEnumerable<string> AllowedValues { get; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ClaimsAuthorizationRequirement requirement) { if (context.User != null) { var found = false; if (requirement.AllowedValues == null || !requirement.AllowedValues.Any()) { found = context.User.Claims.Any(c => string.Equals(c.Type, requirement.ClaimType, StringComparison.OrdinalIgnoreCase)); } else { found = context.User.Claims.Any(c => string.Equals(c.Type, requirement.ClaimType, StringComparison.OrdinalIgnoreCase) && requirement.AllowedValues.Contains(c.Value, StringComparer.Ordinal)); } if (found) { context.Succeed(requirement); } } return Task.CompletedTask; } }
由上咱们能够看的出,ClaimType
和AllowedValues
这两个属性在构造函数中被初始化,分别用来表示当前声明的声明类型和默认容许值。经过HandleRequirementAsync
来受权检验是否完成经过。
基于角色的受权策略,检验当前用户是否拥有约定匹配的角色,若是拥有,则能够访问对应的资源。
源码以下:
public class RolesAuthorizationRequirement : AuthorizationHandler<RolesAuthorizationRequirement>, IAuthorizationRequirement { public RolesAuthorizationRequirement(IEnumerable<string> allowedRoles) { if (allowedRoles == null) { throw new ArgumentNullException(nameof(allowedRoles)); } if (allowedRoles.Count() == 0) { throw new InvalidOperationException(Resources.Exception_RoleRequirementEmpty); } AllowedRoles = allowedRoles; } public IEnumerable<string> AllowedRoles { get; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement) { if (context.User != null) { bool found = false; if (requirement.AllowedRoles == null || !requirement.AllowedRoles.Any()) { // Review: What do we want to do here? No roles requested is auto success? } else { found = requirement.AllowedRoles.Any(r => context.User.IsInRole(r)); } if (found) { context.Succeed(requirement); } } return Task.CompletedTask; } }
其中AllowedRoles
表示目标角色列表的集合。经过HandleRequirementAsync
实现受权检验,调用IsInRole
方法来判断当前用户的ClaimsPrincipal
对象是否有指定的角色。
基于AuthorizationHandlerContext
上下文断言的形式来声明受权。
源码以下:
public class AssertionRequirement : IAuthorizationHandler, IAuthorizationRequirement { public Func<AuthorizationHandlerContext, Task<bool>> Handler { get; } public AssertionRequirement(Func<AuthorizationHandlerContext, bool> handler) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Handler = context => Task.FromResult(handler(context)); } public AssertionRequirement(Func<AuthorizationHandlerContext, Task<bool>> handler) { if (handler == null) { throw new ArgumentNullException(nameof(handler)); } Handler = handler; } public async Task HandleAsync(AuthorizationHandlerContext context) { if (await Handler(context)) { context.Succeed(this); } } }
经过类型为Func<AuthorizationHandlerContext, Task<bool>>
的委托来表示该断言,利用它来受权验证。在HandleAsync
检验方法中,直接调用这个委托对象来完成判断。
基于预约义操做的受权策略。
源码以下:
public class OperationAuthorizationRequirement : IAuthorizationRequirement { public string Name { get; set; } }
由上可知,只是包含一个操做名字的Name
属性,目的在于将受权的目标对象映射到一个预约义的操做上。
出现的IAuthorizationRequirement
对象能够发现,受权要求Requirement
属性是策略的核心方案,每一中Requirement
都表明一种受权方式。
在上文咱们经过构建策略AuthorizationPolicyBuilder
对象的源码能够发现,为咱们提供了多个方法由预约义的IAuthorizationRequirement
类型来建立并将其添加到Requirements
集合中。
实例应用以下:在ConfigureServices中配置服务中
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); var combindPolicy = new AuthorizationPolicyBuilder().RequireClaim("role").Build(); services.AddAuthorization(options => { //DenyAnonymousAuthorizationRequirement options.AddPolicy("DenyAnonyUser", policy => policy.RequireAuthenticatedUser()); //NameAuthorizationRequirement options.AddPolicy("NameAuth", policy => policy.RequireUserName("艾三元")); //ClaimsAuthorizationRequirement options.AddPolicy("ClaimsAuth", policy => policy.RequireClaim("role","admin")); //RolesAuthorizationRequirement options.AddPolicy("RolesAuth", policy => policy.RequireRole("admin","user")); //AssertionRequirement options.AddPolicy("AssertAuth", policy => policy.RequireAssertion(c=>c.User.HasClaim(o=>o.Type=="role"))); //一样可可用直接调用Combind方法,策略AuthorizationPolicy options.AddPolicy("CombindAuth", policy => policy.Combine(combindPolicy)); }); }
以上,分别实现了框架中默认实现的几种IAuthorizationRequirement
实现类型在实际中的应用,经过不一样受权要求实现的策略方式,同时也能够将上面多种方式合并成一个对象,进行调用使用。
固然了,除了自带了这几种默认实现方式以外,咱们也能够经过自定义Requirement
来知足咱们的需求。
这个在上一节初识受权的时候,已经提到了自定义受权这一块,因此在这里再看一次。
定义一个权限策略
PermissionRequirement
,这个策略并包含一些属性。public class PermissionRequirement: IAuthorizationRequirement { public string _permissionName { get; } public PermissionRequirement(string PermissionName) { _permissionName = PermissionName; } }再定义一个策略处理类
public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { var role = context.User.FindFirst(c => c.Type == ClaimTypes.Role); if (role != null) { var roleValue = role.Value; if (roleValue==requirement._permissionName) { context.Succeed(requirement); } } return Task.CompletedTask;配置使用
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); //基于自定义策略受权 services.AddAuthorization(options => { options.AddPolicy("customizePermisson", policy => policy .Requirements .Add(new PermissionRequirement("admin"))); }); //此外,还须要在 IAuthorizationHandler 类型的范围内向 DI 系统注册新的处理程序: services.AddScoped<IAuthorizationHandler, PermissionRequirementHandler>(); // 如前所述,要求可包含多个处理程序。若是为受权层的同一要求向 DI 系统注册多个处理程序,有一个成功就足够了。 }
特别说明
上述使用的处理程序是一对一的关系,当声明要求知足条件的时候,则任务受权成功, 受权成功后,
context.Succeed
将经过知足要求做为其惟一参数调用。可是受权策略中也包含一对多的要求关系,它们属于 & 的关系,只用所有验证经过,才能最终受权成功。可是在有些场景下,咱们可能但愿一个受权策略能够适用多种状况,好比,咱们进入公司时须要出示员工卡才能够被受权进入,可是若是咱们忘了带员工卡,能够去申请一个临时卡,一样能够受权成功。
这里贴一个官方文档的写法: public class BuildingEntryRequirement : IAuthorizationRequirement { } public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BuildingEntryRequirement requirement) { if (context.User.HasClaim(c => c.Type == "BadgeId" && c.Issuer == "http://microsoftsecurity")) { context.Succeed(requirement); } //TODO: Use the following if targeting a version of //.NET Framework older than 4.6: // return Task.FromResult(0); return Task.CompletedTask; } } public class TemporaryStickerHandler : AuthorizationHandler<BuildingEntryRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BuildingEntryRequirement requirement) { if (context.User.HasClaim(c => c.Type == "TemporaryBadgeId" && c.Issuer == "https://microsoftsecurity")) { // We'd also check the expiration date on the sticker. context.Succeed(requirement); } //TODO: Use the following if targeting a version of //.NET Framework older than 4.6: // return Task.FromResult(0); return Task.CompletedTask; } }
咱们定义了两个Handler,可是想让它们获得执行,还须要将其注册到DI系统中:
services.AddSingleton<IAuthorizationHandler, BadgeEntryHandler>(); services.AddSingleton<IAuthorizationHandler, TemporaryStickerHandler>();
确保两个处理程序都已注册。 若是某个处理程序在某一策略评估后使用context.succeed()
来成功 BuildingEntryRequirement ,则策略评估将成功。可是当咱们调用context.Fail()
方法后会将受权结构设置失败,那样的话,最后的结果都是会受权失败的。因此正常状况下。咱们都是只设置标记context.succeed()
。
这里对上文源码中出现的一些声明方法进行说明。
使用 IAuthorizeDate 接口方法。定义受权规则应用于资源所需的数据集。
public interface IAuthorizeData { string Policy { get; set; } string Roles { get; set; } string AuthenticationSchemes { get; set; } }
Policy
:获取或设置肯定对资源的访问的策略名称。
Roles
: 获取或设置以逗号分隔的容许访问资源的角色列表。
AuthenticationSchemes
: 获取或以设置以逗号分隔的方案列表,从中能够构造用户信息。
因此IAuthorizeData
中定义的policy
、roles
、AuthenticationSchemes
三个分别表明着受权系统中的三种受权方式。
具体的使用在后续讲解受权的执行流程中会进行详细介绍。
上面主要讲解了受权在配置方面的源码,原本打算继续接着往下写的,可是考虑到总体篇幅可能会太长了,不便于阅读。
因此受权揭秘的上篇内容就说到这里了,在后续的文章中,会继续深刻了解受权内部机制的奥秘以及是如何实现执行受权流程的。