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
相关产品推荐
相关产品推荐

