首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Spring MVC 實現「記住我」自動登錄:Cookie + Token 方案完整架構

     編輯:程式設計疑難解答

核心思路

**不要直接在 Cookie 存密碼**。標準流程:

  1. 用戶勾選「記住我」登錄成功 → 服務端生成 **隨機 Token (UUID/JWT)**,關聯用戶 ID、過期時間、User-Agent 等指紋信息,存入 **Redis/數據庫**。
  2. 將 Token 寫入 **HttpOnly + Secure + SameSite=Lax** 的 Cookie(如 `remember_me=token_value; Max-Age=2592000; Path=/`)。
  3. 後續請求攜帶 Cookie → 過濾器/攔截器提取 Token → 驗證有效性 → 自動完成認證,注入 `SecurityContext`。
  4. 登出/修改密碼/異地登錄 → 失效對應 Token。

關鍵代碼骨架

1. 登錄成功處理


@PostMapping("/login")
public String login(@RequestParam String username,
                    @RequestParam String password,
                    @RequestParam(required = false) Boolean rememberMe,
                    HttpServletResponse response) {
    User user = userService.authenticate(username, password);
    if (user == null) return "login?error";

    // 生成 Token
    String token = UUID.randomUUID().toString().replace("-", "");
    RememberMeToken rmToken = new RememberMeToken(token, user.getId(), 
        System.currentTimeMillis() + 30 * 24 * 3600 * 1000); // 30 天
    tokenRepository.save(rmToken); // Redis/JPA

    if (Boolean.TRUE.equals(rememberMe)) {
        ResponseCookie cookie = ResponseCookie.from("REMEMBER_ME", token)
            .httpOnly(true).secure(true).path("/").maxAge(30 * 24 * 3600).sameSite("Lax").build();
        response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
    }
    return "redirect:/dashboard";
}

2. 自動登錄過濾器


@Component
public class RememberMeFilter extends OncePerRequestFilter {
    @Autowired TokenRepository tokenRepo;

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) 
            throws ServletException, IOException {
        String token = WebUtils.getCookie(req, "REMEMBER_ME");
        if (token != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            RememberMeToken rmToken = tokenRepo.findByToken(token);
            if (rmToken != null && rmToken.isValid()) {
                UserDetails user = userDetailsService.loadUserById(rmToken.getUserId());
                Authentication auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(auth);
                // 可選:滑動過期續期
            }
        }
        chain.doFilter(req, res);
    }
}

3. Spring Security 配置


http
    .rememberMe()
        .tokenRepository(persistentTokenRepository()) // 持久化倉庫
        .tokenValiditySeconds(30 * 24 * 3600)
        .userDetailsService(userDetailsService)
        .key("unique-app-secret-key"); // 簽名密鑰

安全加固清單

  • Token 必須足夠長且隨機(≥ 128 bit),防暴力枚舉。
  • 綁定設備指紋:User-Agent + IP 段 + 客戶端版本,異常時強制重登。
  • 敏感操作二次驗證:修改密碼、綁定手機、支付需重新輸入密碼/驗證碼。
  • 定期清理過期 Token:定時任務清理 Redis/DB。
  • HTTPS 全站強制:Cookie `Secure` 標誌生效前提。

參考資源

Spring 官方文檔:Remember-Me Authentication
優秀實戰博客:SpringMVC記住密碼功能

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved