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有效期

源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章