ASP.NET Core生成,校驗jwt的(accessToken)訪問令牌和(refreshToken)重新整理令牌示例講解
阿新 • • 發佈:2021-08-08
ASP.NET Core生成,校驗jwt的(accessToken)訪問令牌和(refreshToken)重新整理令牌示例講解
-懶狗如我,解析都寫到註釋裡了,寫的很詳細,不懂的地方翻翻文件
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using jwt.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; namespace jwtTest.Controllers { [ApiController] [Route("api/[controller]")] public class SignInController : Controller { private IConfiguration _configuration { get; set; } // 控制器注入Configuration依賴,方便獲取appsettinfs.json中的SecurityKey public SignInController(IConfiguration config) { _configuration = config; } [HttpGet("login")] public ActionResult Login(string username, string password)//應該寫個LoginDto,我懶了 { if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) { var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); //在此進行賬號密碼認證,此程式碼省略 //------------生成AccessToken---------------------------------- // token中的claims用於儲存自定義資訊,如登入之後的使用者id等 var claims = new[] { new Claim("username",username), new Claim("password",password),//演示用,(不要把密碼寫進token啊喂!!!(#`O′)) //new Claim(ClaimTypes.Role,"admin") new Claim("role","admin")//此寫法和上面寫法效果一樣 }; // 獲取SecurityKey var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa")); //生成Token var token = new JwtSecurityToken( issuer: "cxy", // 釋出者 audience: "myClient", // 接收者 notBefore: DateTime.Now, // token簽發時間 expires: DateTime.Now.AddMinutes(30), // token過期時間 claims: claims, // 該token記憶體儲的自定義欄位資訊 signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) // 用於簽發token的祕鑰演算法 ); //-----------下面是生成RefreshToken-------------------------- var refClaims = new[] { new Claim("role","refresh") }; var refreshToken = new JwtSecurityToken( issuer: "cxy", // 釋出者 audience: "myClient", // 接收者 notBefore: DateTime.Now, // token簽發時間 expires: DateTime.Now.AddDays(7), // token過期時間 claims: refClaims, // 該token記憶體儲的自定義欄位資訊 signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) // 用於簽發token的祕鑰演算法 ); // 返回成功資訊,寫出token return Ok(new { code = 200, message = "登入成功", accessToken = jwtSecurityTokenHandler.WriteToken(token), refreshToken = jwtSecurityTokenHandler.WriteToken(refreshToken) }); } // 返回錯誤請求資訊 return BadRequest(new { code = 400, message = "登入失敗,使用者名稱或密碼為空" }); } //此方法用來重新整理令牌,邏輯是驗證refToken才能進入方法,進入後驗證accessToken除了過期時間項的其他所有項,目的是防止使用者修改許可權等 [HttpPost("refresh")] [Authorize(Roles = "refresh")]//驗證許可權 public ActionResult Refresh(RefreshDto refreshDto) { var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();//這個類是老朋友了 bool isCan =jwtSecurityTokenHandler.CanReadToken(refreshDto.AccessToken);//驗證Token格式 if (!isCan) return BadRequest(new { code = 400, message = "傳入訪問令牌格式錯誤" }); //var jwtToken = jwtSecurityTokenHandler.ReadJwtToken(refreshDto.AccessToken);//轉換型別為token,不用這一行 var validateParameter = new TokenValidationParameters()//驗證引數 { ValidateAudience = true, // 驗證釋出者 ValidateIssuer = true, // 驗證過期時間 ValidateLifetime = false, // 驗證祕鑰 ValidateIssuerSigningKey = true, // 讀配置Issure ValidIssuer = "cxy", // 讀配置Audience ValidAudience = "myClient", // 設定生成token的祕鑰 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa")) }; //驗證傳入的過期的AccessToken SecurityToken validatedToken = null; try { jwtSecurityTokenHandler.ValidateToken(refreshDto.AccessToken, validateParameter,out validatedToken);//微軟提供的驗證方法。那個out傳出的引數,型別是是個抽象類,記得轉換 } catch(SecurityTokenException) { return BadRequest(new {code=400, message= "傳入AccessToken被修改" }); } // 獲取SecurityKey var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("myJWTKeyasasasasa"));//不要學我寫這裡啊,我是懶狗,寫appsettings.json這裡去,寫到類的屬性裡,注入一下 var refClaims = new[] { new Claim("role","refresh") }; var refreshToken = new JwtSecurityToken( issuer: "cxy", // 釋出者 audience: "myClient", // 接收者 notBefore: DateTime.Now, // token簽發時間 expires: DateTime.Now.AddDays(7), // token過期時間 claims: refClaims, // 該token記憶體儲的自定義欄位資訊 signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) // 用於簽發token的祕鑰演算法 ); var jwtToken = validatedToken as JwtSecurityToken;//轉換一下 var accClaims = jwtToken.Claims; var accessToken = new JwtSecurityToken( issuer: "cxy", // 釋出者 //audience: "myClient", // 接收者 notBefore: DateTime.Now, // token簽發時間 expires: DateTime.Now.AddMinutes(30), // token過期時間 claims: accClaims, // 該token記憶體儲的自定義欄位資訊 signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) // 用於簽發token的祕鑰演算法 ); // 返回成功資訊,寫出token return Ok(new { code = 200, message = "令牌重新整理成功", refreshToken =jwtSecurityTokenHandler.WriteToken(refreshToken), accessToken =new JwtSecurityTokenHandler().WriteToken(accessToken) }); } } }