前言
上一節我們講述的書如何使用jwt token,而且上一節的token是要加Authorization:bearer XXXXXXXXXXXX才能訪問。
這一節我們來研究如何自定義類似jwt的token驗證,也就是說直接從header中拿取我們想要的token
自己定制JWT
首先,繼續在上一節的JwtAuthSample項目中的Startup.cs中的ConfigureServices方法中注釋掉以下內容,然后自定義jwt token
public void ConfigureServices(IServiceCollection services) { //將appsettings.json中的JwtSettings部分文件讀取到JwtSettings中,這是給其他地方用的 services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings")); //由於初始化的時候我們就需要用,所以使用Bind的方式讀取配置 //將配置綁定到JwtSettings實例中 var jwtSettings=new JwtSettings(); Configuration.Bind("JwtSettings",jwtSettings); services.AddAuthentication(options=>{ //認證middleware配置 options.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(o=>{ // //主要是jwt token參數設置 // o.TokenValidationParameters=new Microsoft.IdentityModel.Tokens.TokenValidationParameters{ // ValidIssuer =jwtSettings.Issuer, // ValidAudience =jwtSettings.Audience, // //這里的key要進行加密,需要引用Microsoft.IdentityModel.Tokens // IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)) // }; o.SecurityTokenValidators.Clear();//將SecurityTokenValidators清除掉,否則它會在里面拿驗證 o.Events=new JwtBearerEvents{ //重寫OnMessageReceived OnMessageReceived=context=>{ var token=context.Request.Headers["mytoken"]; context.Token=token.FirstOrDefault(); return Task.CompletedTask; } }; }); services.AddMvc(); }
接下來我們新建MyTokenValidator.cs類來驗證token,並讓這個類實現ISecurityTokenValidator接口
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authentication.JwtBearer; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; namespace JwtAuthSample { public class MyTokenValidator : ISecurityTokenValidator { bool ISecurityTokenValidator.CanValidateToken =>true; int ISecurityTokenValidator.MaximumTokenSizeInBytes { get; set; } bool ISecurityTokenValidator.CanReadToken(string securityToken) { return true; } //驗證token ClaimsPrincipal ISecurityTokenValidator.ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { validatedToken=null; //判斷token是否正確 if(securityToken!="abcdefg") return null; //給Identity賦值 var identity=new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); identity.AddClaim(new Claim("name","wyt")); identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType,"admin")); var principle=new ClaimsPrincipal(identity); return principle; } } }
然后我們在Startup.cs的ConfigureServices方法中將我們自定義的MyTokenValidator驗證加進去
o.SecurityTokenValidators.Add(new MyTokenValidator());
這時候我們執行dotnet watch run運行項目,用postman不加header頭或加錯誤的hearder頭,發現無法訪問
我們用正確的自定義token進行訪問
Role以及Claims授權
Role授權
我們之前的授權方式都是添加 [Authorize] 標簽但是由於我們在Claim中設置了Role
所以我們可以將 [Authorize] 標簽寫成[Authorize(Roles="admin")]
只有解析出來的token中的角色為admin才授權成功
Claims授權
要使用Claims授權,我們首先需要在Startup.cs的ConfigureServices方法中添加授權
//添加Claim授權 services.AddAuthorization(options=>{ options.AddPolicy("SuperAdminOnly",policy=>{policy.RequireClaim("SuperAdminOnly");}); });
然后在AuthorizeController.cs生成token的action中的Claim中添加SuperAdminOnly
最后在需要權限認證的地方使用標簽 [Authorize(Policy="SuperAdminOnly")]
我們首先獲取一下token,到jwt官網上解析一下發現token中包含SuperAdminOnly
然后訪問成功