You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring不使用Spring Security实现登录并重定向时安全向其他应用传token

不依赖Spring Security的重定向安全传参实现方案

核心实现逻辑

核心思路为一次性授权码+后端共享存储/加密Cookie组合方案,全程不会将真实token暴露到用户端、浏览器地址栏或访问日志中,具体流程如下:

  • 用户在login应用完成账号密码校验后,后端生成正常业务用的access_token,同时生成一个32位以上无规律的一次性随机授权码
  • 将授权码与access_token、用户ID、10秒有效期绑定,存入两个应用共用的缓存(如Redis)中
  • login应用仅将授权码作为query参数拼接在重定向地址中,跳转到products-list应用的回调接口
  • products-list应用后端拿到授权码后,通过内网接口/共享缓存校验码的有效性,校验通过后取出对应的access_token,立刻删除缓存中的授权码保证仅能消费一次
  • products-list将拿到的access_token存入自身会话(Session)或给用户端设置HttpOnly属性的加密Cookie,后续请求直接使用该凭证调用产品服务即可

关键安全约束

  • 所有存储凭证的Cookie必须开启HttpOnly、Secure(HTTPS环境)、SameSite=Lax/Strict属性,禁止前端JS读取
  • 授权码有效期最多不超过30秒,校验完成后必须立即删除,即使被截获也无法二次使用
  • 若两个应用属于同一父域名(如login.example.com和products.example.com),可直接将加密token的Cookie域设置为父域名example.com,无需通过重定向传参,两个应用可直接共享登录态
  • 授权码的校验接口必须走内部服务调用,不对外暴露公网访问入口

Spring Boot代码示例

login端登录成功重定向逻辑

@PostMapping("/doLogin")
public String doLogin(String username, String password) {
    // 调用用户服务校验账号密码
    UserVO validUser = userService.checkAccount(username, password);
    if (validUser == null) {
        return "redirect:/login?error=invalid_account";
    }
    // 生成业务token和一次性授权码
    String accessToken = JwtUtil.createToken(validUser);
    String authCode = UUID.randomUUID().toString().replace("-", "");
    // 绑定授权码和token存入共享缓存,10秒过期
    redisTemplate.opsForValue().set("auth_code:" + authCode, accessToken, 10, TimeUnit.SECONDS);
    // 重定向到products-list仅携带授权码
    return "redirect:https://products.example.com/callback?code=" + authCode;
}

products-list端授权码校验逻辑

@GetMapping("/callback")
public String authCallback(String code, HttpSession session, HttpServletResponse response) {
    String cacheKey = "auth_code:" + code;
    String accessToken = (String) redisTemplate.opsForValue().get(cacheKey);
    if (accessToken == null) {
        return "redirect:https://login.example.com?error=expired_auth";
    }
    // 立即删除授权码,禁止二次使用
    redisTemplate.delete(cacheKey);
    // 将token存入当前会话或HttpOnly Cookie
    session.setAttribute("access_token", accessToken);
    // 同父域名场景可写共享Cookie
    Cookie tokenCookie = new Cookie("access_token", accessToken);
    tokenCookie.setHttpOnly(true);
    tokenCookie.setSecure(true);
    tokenCookie.setDomain("example.com");
    tokenCookie.setPath("/");
    response.addCookie(tokenCookie);
    return "redirect:/index";
}

内容的提问来源于stack exchange,提问作者moltox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 03:06:04