token过期自动续费方案和实现

(56) 2024-04-23 07:01:01

解决方案

方案1: 每一次请求都进行重新生成一个新的token【频率过高,性能不好】

方案2: 每次登录的时候生成两个token给前端进行返回,一个是用于鉴别用户身份的token,另外一个token则是用于刷新token用的

方案3: 登录过后给前端进行返回token并设置了过期时间30分钟,每次请求的时候前端把token存在请求头里面进行发请求,后端接收请求的时候获取请求头出来进行jwt解析判断过期时间是否小于10分钟,如果小于10分钟就生成新的token在responseHearde进行返回即可

方案二实现

实现过程:

  • 登录成功以后,后端返回 access_token 和 refresh_token,客户端缓存此两种token;
  • 使用 access_token 请求接口资源,成功则调用成功;如果token超时,客户端携带 refresh_token 调用token刷新接口获取新的 access_token;
  • 后端接受刷新token的请求后,检查 refresh_token 是否过期。如果过期,拒绝刷新,客户端收到该状态后,跳转到登录页;如果未过期,生成新的 access_token 返回给客户端。
  • 客户端携带新的 access_token 重新调用上面的资源接口。
  • 客户端退出登录或修改密码后,注销旧的token,使 access_token 和 refresh_token 失效,同时清空客户端的 access_token 和 refresh_toke。

后端

LoginController控制器里

package com.liu.token.controller;

import com.liu.token.domain.Login;
import com.liu.token.utlis.JwtUtil;
import com.liu.token.utlis.ResponseResult;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;

@RestController
@RequestMapping("/user")
public class LoginController { 
   

    @PostMapping("/login")
    public ResponseResult login(@RequestBody Login login){ 
   

        // 验证凭证,1分钟
        String access_token = JwtUtil.createJWT(login.getUsername(), 60*1000l);
        // 验证凭证过期使用这个来刷新凭证,30天
        String refresh_token = JwtUtil.createJWT(login.getUsername(), 30*24*60*60*1000l);

        HashMap<String,String> map=new HashMap<>();
        map.put("access_token",access_token);
        map.put("refresh_token",refresh_token);

        return new ResponseResult(200,"登录成功!",map);
    }

    // 验证路由,不重要,只是提供访问一下
    @PostMapping("/logout")
    public ResponseResult logout(){ 
   
        HashMap<String,Object> map=new HashMap<>();
        map.put("access_token",123456);
        map.put("refresh_token",123456);
        return new ResponseResult(200,"llalaallaal",map);
    }
}

LoginFilter过滤器里

package com.liu.token.filter;

import com.alibaba.fastjson.JSON;
import com.liu.token.common.CustomException;
import com.liu.token.utlis.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@Slf4j
@WebFilter
public class LoginFilter implements Filter { 
   

    // 路径匹配器
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 
   
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        //1、获取本次请求的URI
        String requestURI = request.getRequestURI();
        log.info("拦截到请求:{}", requestURI);

        // 定义不需要处理的请求路径
        String[] urls = new String[]{ 
   
                "/user/login"
        };
        //2、判断本次请求是否需要处理
        boolean check = check(urls, requestURI);

        //3、如果不需要处理,则直接放行
        if (check) { 
   
            log.info("本次请求{}不需要处理", requestURI)
THE END

发表回复