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