2023年6月20日发(作者:)
e的JWT的实现(⾃定义策略形式验证).md既然选择了远⽅,便只顾风⾬兼程 __ HANS许在上篇⽂章, Core的实现,基于中间件来实现。这种⽅式有个缺点,就是所有的URL,要嘛需要验证,要嘛不需要验证,没有办法各取所需,因为我们某个API与另⼀个API的验证⽅式不⼀样。这就引导出“基于⾃定义策略形式下的验证了”。Core 的Authorization实现我们使⽤Core⾃带的Authorization(认证与授权)来实现。⼤家可以先看下微软官⽅的1. 微软官⽅例⼦:1.1 定义策略1. internal class MinimumAgeAuthorizeAttribute : AuthorizeAttribute
2. {
3. const string POLICY_PREFIX = "MinimumAge";
4. public MinimumAgeAuthorizeAttribute(int age) => Age = age;
5. // Get or set the Age property by manipulating the underlying Policy property
6. public int Age
7. {
8. get
9. {
10. if (se(ing(POLICY_), out var age))
11. {
12. return age;
13. }
14. return default(int);
15. }
16. set
17. {
18. Policy = $"{POLICY_PREFIX}{ng()}";
19. }
20. }
21. }
1.2 使⽤策略1. [MinimumAgeAuthorize(10)] 2. public IActionResult RequiresMinimumAge10()
这样在执⾏RequiresMinimumAge10会先执⾏MinimumAgeAuthorize策略,很像MVC的Attribute特性,但内部⼜不像,在这边就不多做解释了,微软的Core官⽅⽂档讲的很清楚。⼤家去看下就清楚了。2. JWT的⾃定义策略形式的实现2.1 了解IAuthorizationRequirementIAuthorizationRequirement表⽰授权要求,⽤户可以继承这个接⼝,实现⾃⼰认证与授权的要求,⽐如上⾯的⽚段代码,它就继承该接⼝,并有个字段Age,也就是这个策略有年龄的要求,这个要求可以带到我们后⾯验证的⽅法⾥⾯。我们往下看。2.2 继承IAuthorizationRequirement所以我们实现了JwtAuthorizeBaseRequiremente该接⼝,并继承IAuthorizationRequirement,可以看到我们的要求是⼀个叫validatePayLoad的委托函数,委托函数的⼊参是字典,JWT,字典便是上篇⽂章说的JWT的负载部分了。⽽返回参数是bool,便代表我们⾃定义的策略验证JWT是否成功。IJwtAuthorizRequiremente继承了IAuthorizationRequirement1. public class JwtAuthorizeBaseRequiremente : IJwtAuthorizRequiremente
2. {
3. protected internal Func
4. {
5. return true;
6. };
7.
8. public virtual IJwtAuthorizRequiremente SetValidateFunc(Func
9.
10. {
11. tePayLoad = func ?? tePayLoad;
12. return this;
13. }
14. }
2.3 了解AuthorizationHandlerAuthorizationHandler为特定需求类型调⽤的授权处理程序的基类。也就是说我们处理策略是会到这个基类来处理,并且判断是否认证成功,也就是授权成功。2.4 继承AuthorizationHandlerJwtAuthorizeHandler继承AuthorizationHandler并实现泛型JwtAuthorizeBaseRequiremente的定义,这样⼦我们的⾃定义的策略委托验证函数就会传递到这个处理类。我们需要重写HandleRequirementAsync来⾃定已处理。可以看到,最终我们还是调⽤上篇⽂章所讲的验证函数_te,⼤家不清楚可以去看上篇⽂章。⽽tePayLoad便是我们稍后再外⾯⾃定义的验证函数了。1. public class JwtAuthorizeHandler : AuthorizationHandler
2. {
3. private readonly JsonWebTokenSetting _setting; 4. private readonly IJsonWebTokenValidate _jsonWebTokenValidate;
5.
6. public JwtAuthorizeHandler(IOptions
7. {
8. this._setting = ;
9. this._jsonWebTokenValidate = jsonWebTokenValidate;
10. }
11.
12. ///
13. /// 验证JWT
14. ///
15. ///
16. ///
17. ///
18. protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtAuthorizeBaseRequiremente requirement)
19. {
20. var httpContext = (ce as AuthorizationFilterContext).HttpContext;
21.
22. var result = Value("Authorization", out StringValues authStr);
23. if (!result || OrEmpty(ng()))
24. {
25. throw new UnauthorizedAccessException("未授权,请传递Header头的Authorization参数。");
26. }
27. result = result && _te(ng().Substring("Bearer ".Length).Trim(), _setting,
tePayLoad);
28. if (!result)
29. {
30. throw new UnauthorizedAccessException("验证失败,请查看传递的参数是否正确或是否有权限访问该地址。");
31. }
32. d(requirement);
33. return tedTask;
34. }
35. }
2.5 怎么使⽤呢?我们需要在⽂件进⾏注册服务。其中CommonAuthorize继承JwtAuthorizeBaseRequiremente,并将⾃定义的策略⽅法,传递进去。其中common是策略名称。可以多个定义策略1. public void ConfigureServices(IServiceCollection services) 2. {
3. (Configuration);
4. ().SetCompatibilityVersion(n_2_2);
5. horization(option =>
6. {
7. #region ⾃定义验证策略 可以⼀直⾃定义策略
8. icy("common", policy => (new CommonAuthorize().
9. SetValidateFunc((playLoad, sertting) =>
10. {
11. //每个策略⾃定义验证函数,playLoad为带过来的参数字典,setting为失效时间与秘钥
12. return true;
13. })));
14. #endregion ⾃定义验证策略
15. }).AddAuthentication(option =>
16. {
17. tScheme = ticationScheme;
18. });
19. }
接着我们在想要的Controller或者Action的头部使⽤[Authorize(Policy = "common")],这样每次进到相对应的Controller或者Action,会先进⾏策略验证,⽽我们这边验证的便是JWT了。总结⼀下,我们在这篇⽂章是基于上篇⽂章的,所以JWT的⽣成与验证我们就不讲了。两篇⽂章讲了JWT的验证,两种⽅式有好有坏,⼤家可以根据⾃⼰的模式进⾏选择。1.使⽤管道的⽅式,感觉⽅便点,清晰点2. 使⽤⾃定义策略的⽅式,效率稍微⾼⼀点,毕竟不是所有的请求都会进⾏是否可以匿名访问运算和建⽴管道的消耗,只有加⼊Authorize属性的Controller和Action的才会进⼊最后附上,或者直接到我的上看看。后⾯要是有时间,可以讲下IdentityServer4的OAuth2的授权与认证。
2023年6月20日发(作者:)
e的JWT的实现(⾃定义策略形式验证).md既然选择了远⽅,便只顾风⾬兼程 __ HANS许在上篇⽂章, Core的实现,基于中间件来实现。这种⽅式有个缺点,就是所有的URL,要嘛需要验证,要嘛不需要验证,没有办法各取所需,因为我们某个API与另⼀个API的验证⽅式不⼀样。这就引导出“基于⾃定义策略形式下的验证了”。Core 的Authorization实现我们使⽤Core⾃带的Authorization(认证与授权)来实现。⼤家可以先看下微软官⽅的1. 微软官⽅例⼦:1.1 定义策略1. internal class MinimumAgeAuthorizeAttribute : AuthorizeAttribute
2. {
3. const string POLICY_PREFIX = "MinimumAge";
4. public MinimumAgeAuthorizeAttribute(int age) => Age = age;
5. // Get or set the Age property by manipulating the underlying Policy property
6. public int Age
7. {
8. get
9. {
10. if (se(ing(POLICY_), out var age))
11. {
12. return age;
13. }
14. return default(int);
15. }
16. set
17. {
18. Policy = $"{POLICY_PREFIX}{ng()}";
19. }
20. }
21. }
1.2 使⽤策略1. [MinimumAgeAuthorize(10)] 2. public IActionResult RequiresMinimumAge10()
这样在执⾏RequiresMinimumAge10会先执⾏MinimumAgeAuthorize策略,很像MVC的Attribute特性,但内部⼜不像,在这边就不多做解释了,微软的Core官⽅⽂档讲的很清楚。⼤家去看下就清楚了。2. JWT的⾃定义策略形式的实现2.1 了解IAuthorizationRequirementIAuthorizationRequirement表⽰授权要求,⽤户可以继承这个接⼝,实现⾃⼰认证与授权的要求,⽐如上⾯的⽚段代码,它就继承该接⼝,并有个字段Age,也就是这个策略有年龄的要求,这个要求可以带到我们后⾯验证的⽅法⾥⾯。我们往下看。2.2 继承IAuthorizationRequirement所以我们实现了JwtAuthorizeBaseRequiremente该接⼝,并继承IAuthorizationRequirement,可以看到我们的要求是⼀个叫validatePayLoad的委托函数,委托函数的⼊参是字典,JWT,字典便是上篇⽂章说的JWT的负载部分了。⽽返回参数是bool,便代表我们⾃定义的策略验证JWT是否成功。IJwtAuthorizRequiremente继承了IAuthorizationRequirement1. public class JwtAuthorizeBaseRequiremente : IJwtAuthorizRequiremente
2. {
3. protected internal Func
4. {
5. return true;
6. };
7.
8. public virtual IJwtAuthorizRequiremente SetValidateFunc(Func
9.
10. {
11. tePayLoad = func ?? tePayLoad;
12. return this;
13. }
14. }
2.3 了解AuthorizationHandlerAuthorizationHandler为特定需求类型调⽤的授权处理程序的基类。也就是说我们处理策略是会到这个基类来处理,并且判断是否认证成功,也就是授权成功。2.4 继承AuthorizationHandlerJwtAuthorizeHandler继承AuthorizationHandler并实现泛型JwtAuthorizeBaseRequiremente的定义,这样⼦我们的⾃定义的策略委托验证函数就会传递到这个处理类。我们需要重写HandleRequirementAsync来⾃定已处理。可以看到,最终我们还是调⽤上篇⽂章所讲的验证函数_te,⼤家不清楚可以去看上篇⽂章。⽽tePayLoad便是我们稍后再外⾯⾃定义的验证函数了。1. public class JwtAuthorizeHandler : AuthorizationHandler
2. {
3. private readonly JsonWebTokenSetting _setting; 4. private readonly IJsonWebTokenValidate _jsonWebTokenValidate;
5.
6. public JwtAuthorizeHandler(IOptions
7. {
8. this._setting = ;
9. this._jsonWebTokenValidate = jsonWebTokenValidate;
10. }
11.
12. ///
13. /// 验证JWT
14. ///
15. ///
16. ///
17. ///
18. protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtAuthorizeBaseRequiremente requirement)
19. {
20. var httpContext = (ce as AuthorizationFilterContext).HttpContext;
21.
22. var result = Value("Authorization", out StringValues authStr);
23. if (!result || OrEmpty(ng()))
24. {
25. throw new UnauthorizedAccessException("未授权,请传递Header头的Authorization参数。");
26. }
27. result = result && _te(ng().Substring("Bearer ".Length).Trim(), _setting,
tePayLoad);
28. if (!result)
29. {
30. throw new UnauthorizedAccessException("验证失败,请查看传递的参数是否正确或是否有权限访问该地址。");
31. }
32. d(requirement);
33. return tedTask;
34. }
35. }
2.5 怎么使⽤呢?我们需要在⽂件进⾏注册服务。其中CommonAuthorize继承JwtAuthorizeBaseRequiremente,并将⾃定义的策略⽅法,传递进去。其中common是策略名称。可以多个定义策略1. public void ConfigureServices(IServiceCollection services) 2. {
3. (Configuration);
4. ().SetCompatibilityVersion(n_2_2);
5. horization(option =>
6. {
7. #region ⾃定义验证策略 可以⼀直⾃定义策略
8. icy("common", policy => (new CommonAuthorize().
9. SetValidateFunc((playLoad, sertting) =>
10. {
11. //每个策略⾃定义验证函数,playLoad为带过来的参数字典,setting为失效时间与秘钥
12. return true;
13. })));
14. #endregion ⾃定义验证策略
15. }).AddAuthentication(option =>
16. {
17. tScheme = ticationScheme;
18. });
19. }
接着我们在想要的Controller或者Action的头部使⽤[Authorize(Policy = "common")],这样每次进到相对应的Controller或者Action,会先进⾏策略验证,⽽我们这边验证的便是JWT了。总结⼀下,我们在这篇⽂章是基于上篇⽂章的,所以JWT的⽣成与验证我们就不讲了。两篇⽂章讲了JWT的验证,两种⽅式有好有坏,⼤家可以根据⾃⼰的模式进⾏选择。1.使⽤管道的⽅式,感觉⽅便点,清晰点2. 使⽤⾃定义策略的⽅式,效率稍微⾼⼀点,毕竟不是所有的请求都会进⾏是否可以匿名访问运算和建⽴管道的消耗,只有加⼊Authorize属性的Controller和Action的才会进⼊最后附上,或者直接到我的上看看。后⾯要是有时间,可以讲下IdentityServer4的OAuth2的授权与认证。
发布评论