我所使用的环境如下:
ASP.NET CORE 6.0
Furion 3.7.5
可能有些人还不知道这个Furion是什么东西,这里给出它的开发文档的连接,有兴趣的朋友可以了解一下这个框架。这个框架是对ASP.NET CORE框架的一个封装,使用起来挺方便的,值得推荐给大家。
开发文档链接:1.1 介绍 | Furion
一般情况下我们使用一个token来认证,但是这样的话有一个问题:服务端生成的token的有效期是固定的,默认20分钟。当用户在界面上操作了20分钟以后,这个token就失效了,系统会返回401认证失败,这个情况在我看来是不太合理的。比如用户在执行添加操作,在提交的时候告诉你认证失败了,重新登录后之前添加的内容就要重新写一次,那他肯定要抓狂了,嘴里骂着这是什么烂软件。
刷新token的有效期默认是30天,可以自定义
当我们用2个token来认证的时候,流程是这样的:用户登录成功后,返回2个token,一个是正常的token,一个是刷新token。每次请求时都带上这2个token(其实刷新token不用每次携带,只在正常token快失效的携带就可以了,这里需要前端做一个判断,如果前端不愿意判断,每次都携带也可以,只是多耗费一点流量罢了)。当token有效期过了,系统会判断有效期超过的时间是不是大于刷新token的有效期,如果大于就返回401(因为刷新token的有效期很长,所以这种情况基本不会发生,你添加一个数据会用30天吗?),反之则会刷新正常的token,把正常token的有效期延长,刷新token的有效期也会相应的延长。然后把这2个新token放到http的返回头里面,前端接收到这2个新的token之后,替换之前的token。
添加自定义认证代码:
- var jwtSetOption = JWTHelper.SetValidParameter();
- builder.Services.AddJwt
(null,jwtSetOption);
设置JWT的认证参数:
- public static JWTSettingsOptions SetValidParameter()
- {
- JWTSettingsOptions options = new JWTSettingsOptions()
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = App.Configuration["JWTSettings:IssuerSigningKey"],
- ValidateIssuer = true,
- ValidIssuer = App.Configuration["JWTSettings:ValidIssuer"],
- ValidateAudience = true,
- ValidAudience = App.Configuration["JWTSettings:ValidAudience"],
- ValidateLifetime = true,
- Algorithm = SecurityAlgorithms.HmacSha256,
- ClockSkew = 0
- };
- return options;
- }
自定义认证:
- public class JwtHandler : AppAuthorizeHandler
- {
- public override async Task HandleAsync(AuthorizationHandlerContext context)
- {
- if (JWTHelper.AutoRefreshToken(context))
- await AuthorizeHandleAsync(context);
- else
- context.Fail();
- }
- }
JWTHelper.AutoRefreshToken这个函数是我封装的方法,这个方法的代码如下:
- public static bool AutoRefreshToken(AuthorizationHandlerContext context)
- {
- return JWTEncryption.AutoRefreshToken(context,
- context.GetCurrentHttpContext());
- }
引用的命名空间:using Furion.DataEncryption;
生成刷新token,这个token参数就是调用JWTEncryption.Encrypt函数生成的正常的token,这里可以自定义刷新token的有效期:
JWTEncryption.GenerateRefreshToken(token);
代码就这么几行,但是这里有几个坑要填
1、AddJwt必须在AddControllers之前调用,不然自定义认证的HandleAsync函数就不会被调用。
2、在配置JWT认证参数的时候,参数配置是这样的:
- "JWTSettings": {
- "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true
- "IssuerSigningKey": "", // 密钥,string 类型,必须是复杂密钥,长度大于16
- "ValidateIssuer": true, // 是否验证签发方,bool 类型,默认true
- "ValidIssuer": "", // 签发方,string 类型
- "ValidateAudience": true, // 是否验证签收方,bool 类型,默认true
- "ValidAudience": "", // 签收方,string 类型
- "ValidateLifetime": true, // 是否验证过期时间,bool 类型,默认true,建议true
- "ExpiredTime": 20, // 过期时间,long 类型,单位分钟,默认20分钟
- "ClockSkew": 5, // 过期时间容错值,long 类型,单位秒,默认 5秒
- "Algorithm": "HS256" // 加密算法,string 类型,默认 HS256
- }
这里的参数名字不要去改,因为在JWTEncryption.AutoRefreshToken函数内部会读取这个配置,如果名字改了就读取不到了,读取不到就会使用默认的值。这个时候你可能就会奇怪,明明我在配置文件里配置的过期时间是60分钟,但是生成的新的token的过期时间变成了20分钟。我就是因为手贱改了配置参数的名称才发现了这个问题。