既然選擇了遠方,便只顧風雨兼程 __ 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的受權與認證。