ASP.NET Core生成,校验jwt的(accessToken)访问令牌和(refreshToken)刷新令牌示例讲解

  • A+
所属分类:.NET技术
摘要

-懒狗如我,解析都写到注释里了,写的很详细,不懂的地方翻翻文档微软文档


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)             });         }     } }