1. 程式人生 > 其它 >Token+Redis登入認證

Token+Redis登入認證

首發於Enaium的個人部落格


首先需要了解一下大概的步驟

  1. 登入生成一個Token存入Redis有效期為30分鐘,返回到前端
  2. 之後前端每次請求,帶上登入時返回的Token
  3. 伺服器判斷前端帶來的Token是否在Redis伺服器中
  4. 存在放行並且重置Token有效期,不存在攔截

一個簡簡單單的登入請求

@RequestMapping("/login")
@ResponseBody
public Result<String> login(@RequestBody UserDTO userDTO) {
    var byUsernameAndPassword = mapper.getByUsernameAndPassword(userDTO.getUsername(), userDTO.getPassword());
    if (byUsernameAndPassword != null) {
        return new Result<>(true, "login success");
    }
    return new Result<>(false, "wrong username or password");
}

生成一個UUID存入Redis,值為使用者的ID,並且設定有效期為30分鐘

var uuid = "user-token:" + UUID.randomUUID();
            redisTemplate.opsForValue().set(uuid, byUsernameAndPassword.getId().toString(), 30, TimeUnit.MINUTES);
            return new Result<>(true, uuid);

接下來直寫攔截器,重寫addInterceptors方法

@Configuration
public class RequestInterceptor implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    }
}

使用HandlerInterceptor重寫preHandle方法,登入和註冊不用攔截

registry.addInterceptor(new HandlerInterceptor() {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }
}).excludePathPatterns("/user/login", "/user/register");

前端在請求頭中放入Token,之後從請求頭中獲取Token,從Redis中獲取token是否存在,存在返回為true並且重新設定有效期,不存在就返回false設定響應狀態為401

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    var token = request.getHeader("token");
    if (token != null && redisTemplate.opsForValue().get(token) != null) {
        redisTemplate.expire(token, 30, TimeUnit.MINUTES);
        return true;
    }
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    return false;
}

到這裡一個簡簡單單的Token登入認證就完成了,不過還有個小問題,那就是隻有訪問需要攔截的地址時,有效期才會被重置,使用者一直訪問不需要攔截的地址,Token有效期那就不會被重置,所以解決方法也很簡單,那就是在登入認證的攔截器之前再加一個攔截器,用來重新整理Token有效期