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)
});
}
}
}
ASP.NET Core生成,校验jwt的(accessToken)访问令牌和(refreshToken)刷新令牌示例讲解