项目采用vs2019开发基于.net core5.0的web api方式,前端采用原生html5,css,jquery实现。
大概思路:
后端检测到token过期后,执行刷新方法,然后将刷新好的token放入response响应头中,在前端页面通过ajax方式获取响应头,如果不为空,则存入到localStorage中,每次发送ajax时,会将localStorage里面存的token取出,一起发送到后端
下面直接上实现代码
后端
由于本项目采用的前后分离的,所以后端做了跨域请求,前端采用web storm开发
在Startup中,添加允许暴露自定义头部的请求
在ConfigureServices方法中
//注册Cors服务
services.AddCors(options =>
{
options.AddPolicy(corsPolicyName,
builder =>
{
//将指定的源添加到策略
builder.WithOrigins("http://localhost:65000").AllowAnyHeader().AllowCredentials().WithExposedHeaders(new string[] { "tokenStr666" });//前后分离中,这个地址为前端发送过来的IP地址和端口号
});
});
当token过期时,执行刷新操作,需传入旧的token
public static string refreshToken(string accessToken)
{
if (string.IsNullOrWhiteSpace(accessToken)) return "404";
var userClaims = GetClaimsPrincipalFromAccessToken(accessToken);
if (userClaims == null) return "404";
//声明
var claims = new[]
{
//用户ID
new Claim(ClaimTypes.Sid,userClaims.FindFirst(u=>u.Type.Equals(ClaimTypes.Sid)).Value),
//用户名
new Claim(ClaimTypes.Name,userClaims.FindFirst(u=>u.Type.Equals(ClaimTypes.Name)).Value)
};
//设置秘钥
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtTokenString));
//设置凭证
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//生成token
var jwtToken = new JwtSecurityToken(
"Issuer","Audience",claims,
expires:DateTime.UtcNow.AddMinutes(10),//刷新后更新10分钟有效期
//expires: DateTime.UtcNow.AddSeconds(5),
signingCredentials:credentials
);
string newToken =new JwtSecurityTokenHandler().WriteToken(jwtToken);
return newToken;
}
//刷新好的token,保存到response中
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
//核心语句
context.HttpContext.Response.Headers.Add("tokenStr666",token);
//前端接收发送token方式
//以下为全域ajax方式实现,只需要在需要用的js文件中加载该文件即可
layui.use(['form', 'table'], function () { let $ = layui.jquery; //let api="http://localhost:3000/api/"; $.ajaxSetup({ cache : false, async:false, beforeSend:function(xhr){ //console.log('ajax开始发送前的准备,往头部放入token.........................................................'); let tokenStr=localStorage.getItem("token"); if(tokenStr!=null){ xhr.setRequestHeader('Authorization', 'Bearer '+tokenStr); } }, success(result,status,xhr){ /*console.log('来自jq.js的success的result值21:',result); console.log('来自jq.js的success的status值21:',status); console.log('来自jq.js的success的xhr值21:',xhr);*/ }, //这里可以理解为token没有或者已经过期失效 error : function(xhr) { console.log('出错啦,错误代码22',xhr.responseText); layer.msg(xhr.responseText); }, complete:function (event,xhr,options) { //console.log('event22',event); // console.log('event.getResponseHeader(tokenstr666)22',event.getResponseHeader('tokenstr666')); if(event.getResponseHeader('tokenstr666')!==null){ console.log('更新token'); localStorage.setItem('token',event.getResponseHeader('tokenstr666')); } } }); });