既然选择了远方,便只顾风雨兼程 __ HANS许html
在上篇文章,咱们讲了JWT在ASP.NET Core的实现,基于中间件来实现。这种方式有个缺点,就是全部的URL,要嘛须要验证,要嘛不须要验证,没有办法各取所需,由于咱们某个API与另外一个API的验证方式不同。这就引导出“基于自定义策略形式下的验证了”。git
ASP.NET Core 的Authorization实现
咱们使用Core自带的Authorization(认证与受权)来实现。你们能够先看下微软官方的策略受权github
-
微软官方例子:
1.1 定义策略json
- internal class MinimumAgeAuthorizeAttribute : AuthorizeAttribute
- {
- const string POLICY_PREFIX = "MinimumAge";
- public MinimumAgeAuthorizeAttribute(int age) => Age = age;
-
- public int Age
- {
- get
- {
- if (int.TryParse(Policy.Substring(POLICY_PREFIX.Length), out var age))
- {
- return age;
- }
- return default(int);
- }
- set
- {
- Policy = $"{POLICY_PREFIX}{value.ToString()}";
- }
- }
- }
1.2 使用策略ide
- [MinimumAgeAuthorize(10)]
- public IActionResult RequiresMinimumAge10()
这样在执行RequiresMinimumAge10
会先执行MinimumAgeAuthorize
策略,很像MVC的Attribute
特性,
但内部又不像,在这边就很少作解释了,微软的Core官方文档讲的很清楚。你们去看下就清楚了。函数
-
JWT的自定义策略形式的实现
2.1 了解IAuthorizationRequirement
IAuthorizationRequirement
表示受权要求,用户能够继承这个接口,实现本身认证与受权的要求,好比上面的片断代码,它就继承该接口,并有个字段Age
,也就是这个策略有年龄的要求,这个要求能够带到咱们后面验证的方法里面。咱们往下看。ui
2.2 继承IAuthorizationRequirement
因此咱们实现了JwtAuthorizeBaseRequiremente
该接口,并继承IAuthorizationRequirement
,能够看到咱们的要求是一个叫validatePayLoad
的委托函数,委托函数的入参是字典,JWT,字典即是上篇文章说的JWT的负载部分了。而返回参数是bool,便表明咱们自定义的策略验证JWT是否成功。IJwtAuthorizRequiremente
继承了IAuthorizationRequirement
this
- public class JwtAuthorizeBaseRequiremente : IJwtAuthorizRequiremente
- {
- protected internal Func<Dictionary<string, string>, JsonWebTokenSetting, bool> validatePayLoad = (a, b) =>
- {
- return true;
- };
-
- public virtual IJwtAuthorizRequiremente SetValidateFunc(Func<Dictionary<string, string>, JsonWebTokenSetting, bool> func)
-
- {
- this.validatePayLoad = func ?? this.validatePayLoad;
- return this;
- }
- }
2.3 了解AuthorizationHandler
AuthorizationHandler
为特定需求类型调用的受权处理程序的基类。也就是说咱们处理策略是会到这个基类来处理,而且判断是否定证成功,也就是受权成功。spa
2.4 继承AuthorizationHandler
JwtAuthorizeHandler
继承AuthorizationHandler
并实现泛型JwtAuthorizeBaseRequiremente
的定义,这样子咱们的自定义的策略委托验证函数就会传递到这个处理类。咱们须要重写HandleRequirementAsync
来自定已处理。能够看到,最终咱们仍是调用上篇文章所讲的验证函数_jsonWebTokenValidate.Validate
,你们不清楚能够去看上篇文章。而requirement.validatePayLoad
即是咱们稍后再外面自定义的验证函数了。code
- public class JwtAuthorizeHandler : AuthorizationHandler<JwtAuthorizeBaseRequiremente>
- {
- private readonly JsonWebTokenSetting _setting;
- private readonly IJsonWebTokenValidate _jsonWebTokenValidate;
-
- public JwtAuthorizeHandler(IOptions<JsonWebTokenSetting> setting, IJsonWebTokenValidate jsonWebTokenValidate)
- {
- this._setting = setting.Value;
- this._jsonWebTokenValidate = jsonWebTokenValidate;
- }
-
-
-
-
-
-
-
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtAuthorizeBaseRequiremente requirement)
- {
- var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;
-
- var result = httpContext.Request.Headers.TryGetValue("Authorization", out StringValues authStr);
- if (!result || string.IsNullOrEmpty(authStr.ToString()))
- {
- throw new UnauthorizedAccessException("未受权,请传递Header头的Authorization参数。");
- }
- result = result && _jsonWebTokenValidate.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), _setting, requirement.validatePayLoad);
- if (!result)
- {
- throw new UnauthorizedAccessException("验证失败,请查看传递的参数是否正确或是否有权限访问该地址。");
- }
- context.Succeed(requirement);
- return Task.CompletedTask;
- }
- }
2.5 怎么使用呢?
-
咱们须要在Startup.cs
文件进行注册服务。其中CommonAuthorize
继承JwtAuthorizeBaseRequiremente
,并将自定义的策略方法,传递进去。其中common
是策略名称。能够多个定义策略
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddJwt(Configuration);
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- services.AddAuthorization(option =>
- {
- #region 自定义验证策略 能够一直自定义策略
- option.AddPolicy("common", policy => policy.Requirements.Add(new CommonAuthorize().
- SetValidateFunc((playLoad, sertting) =>
- {
-
- return true;
- })));
- #endregion 自定义验证策略
- }).AddAuthentication(option =>
- {
- option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
- });
- }
-
接着咱们在想要的Controller
或者Action
的头部使用[Authorize(Policy = "common")]
,这样每次进到相对应的Controller
或者Action
,会先进行策略验证,而咱们这边验证的即是JWT了。
总结一下,咱们在这篇文章是基于上篇文章的,因此JWT的生成与验证咱们就不讲了。两篇文章讲了JWT的验证,两种方式有好有坏,你们能够根据本身的模式进行选择。
1.使用管道的方式,感受方便点,清晰点
2. 使用自定义策略的方式,效率稍微高一点,毕竟不是全部的请求都会进行是否能够匿名访问运算和创建管道的消耗,只有加入Authorize属性的Controller和Action的才会进入
最后附上源码,或者直接到个人GitHub上看看。后面要是有时间,能够讲下IdentityServer4
的OAuth2的受权与认证。