当前位置:首页 » 《关于电脑》 » 正文

Redis实现JWT(JSON Web TOKEN)自动延长TOKEN过期时间

12 人参与  2024年09月11日 16:01  分类 : 《关于电脑》  评论

点击全文阅读


JWT是JSON WEB TOKEN的简写,常用于生成及校验Token。

常见的使用场景为:用户携带name和秘钥访问后端服务器,应用后端在校验通过后使用JWT生成并返回一串Token,后续用户只需要携带此Token就可以访问服务器,在此不多赘述。

本文目的是基于redis实现token自动更新其过期时间,在校验用户姓名和密码后使用JWT工具类生成会过期的Token,当用户携带此Token访问服务器后会自动延长其过期时间。

例如:用户A携带账户名及秘钥获取token,该token过期时间为2小时,过了1小时后用户再次携带该token访问系统,系统会自动将该token过期时间设置为此刻往后2小时候过期。

1、前提

1.1、JWT工具类
public class JwtUtil {  public static final String JWT_ID = "dshsdhsdgjhjdsh";  /**   * jwt 加密解密密钥(可自行填写Base64加密)   */  private static final String JWT_SECRET = "ahsagsggfTwGGFff";  /**   * 创建JWT   */  public static String createJwt(Map<String, Object> claims, Long time) {    //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;    Date now = new Date(System.currentTimeMillis());    SecretKey secretKey = generalKey();    //下面就是在为payload添加各种标准声明和私有声明了,new一个JwtBuilder,设置jwt的body    JwtBuilder builder = Jwts.builder()            //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的            .setClaims(claims)            //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。            .setId(JWT_ID)            //iat: jwt的签发时间            .setIssuedAt(now)            //设置过期时间            .setExpiration(new Date(System.currentTimeMillis() + time))            //设置签名使用的签名算法和签名使用的秘钥            .signWith(signatureAlgorithm, secretKey);    return builder.compact();  }  /**   * 验证jwt   */  public static Claims verifyJwt(String token) {    //签名秘钥,和生成的签名的秘钥一模一样    SecretKey key = generalKey();    Claims claims;    try {      //得到DefaultJwtParser      claims = Jwts.parser()              //设置签名的秘钥              .setSigningKey(key)              .parseClaimsJws(token).getBody();    } catch (Exception e) {      claims = null;    }//设置需要解析的jwt    return claims;  }  /**   * 刷新token并设置过期时间   * @param token 旧的token   * @param newExpirationInMillis 过期时间,单位毫秒   * @return 新的jwt token   */  public static String updateTokenExpiration(String token, Long newExpirationInMillis) {    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;    SecretKey secretKey = generalKey();    Claims claims = Jwts.parser()            .setSigningKey(secretKey)            .parseClaimsJws(token)            .getBody();    claims.setExpiration(new Date(System.currentTimeMillis()+newExpirationInMillis));    return Jwts.builder()            .setClaims(claims)            .setId(JWT_ID)            .signWith(signatureAlgorithm, secretKey)            .compact();  }  /**   * 由字符串生成加密key   *   * @return   */  public static SecretKey generalKey() {    byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);    SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");    return key;  }}
1.2、Maven依赖
<dependency>    <groupId>io.jsonwebtoken</groupId>    <artifactId>jjwt</artifactId>    <version>0.9.1</version></dependency>
1.3、配置过期时间及其他常量
private static final long EXPIRE_TIME = 7200 * 1000;private static final String USER_NAME = "user_name";private static final String SECRET = "password";private static final String JWT_TOKEN_USERNAME = "jwt_token:username";

2、思路与流程

2.1、生成Token

步骤一:用户携带userName和Password访问后端接口,当校验通过后使用JWT工具类生成Token;

 //校验appId和秘钥...//如果校验通过则生成JWT HashMap<String, Object> jwtMap = new HashMap<>(5); jwtMap.put(USER_NAME, userName); jwtMap.put(SECRET, password); //生成JWT String jwt = JwtUtil.createJwt(jwtMap, EXPIRE_TIME);

步骤二:将生成Token及过期时间放入redis数据库中

  String oldToken = (String) redisClient.get(JWT_TOKEN_USERNAME + USER_NAME);  //判断是否存在旧的Token  if (oldToken != null) {      redisClient.delete(oldToken);   }   //多次获取token只生效最后一次   redisClient.set(jwt, jwt, EXPIRE_TIME);   redisClient.set(JWT_TOKEN_USERNAME + appId, jwt, EXPIRE_TIME);
2.2、校验Token
 String valueToken = (String) redisClient.get(token); if (valueToken == null) {      //输出无效信息     log.error("TOKEN:{}无效", token);     //抛异常    throw new Exception();  } else {  Claims claims = JwtUtil.verifyJwt(valueToken);  if (claims == null) {      log.error("TOKEN:{}已过期", token);      throw new Exception();  }   String newToken = JwtUtil.updateTokenExpiration(valueToken, EXPIRE_TIME);   log.info("刷新后的token为:{}", newToken);   redisClient.set(token, newToken, EXPIRE_TIME);   String appKey = (String) claims.get(USER_NAME);   redisClient.expire(JWT_TOKEN_USERNAME + username, EXPIRE_TIME,TimeUnit.MILLISECONDS);   return claims.get(USER_NAME);        }


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/158333.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1