Spring MVC集成Spring Cloud Gateway OAuth2.0:如何将令牌回传至MVC应用
如何将网关的OAuth2令牌传递给MVC应用
针对你提出的场景(Spring Boot MVC+Thymeleaf应用通过Spring Cloud Gateway访问微服务,认证逻辑集中在网关层),以下是几种实用方案,实现网关认证成功后将AccessToken、IdToken返回给MVC应用复用:
方案1:网关暴露自定义令牌获取端点
网关作为OAuth2客户端,认证成功后会在自身会话中存储已授权的令牌信息。可以在网关中新增一个受保护的端点,供MVC应用获取令牌:
- 在网关中创建控制器,注入
OAuth2AuthorizedClientService和SecurityContextHolder:
@RestController @RequestMapping("/api/token") @PreAuthorize("isAuthenticated()") public class TokenEndpointController { private final OAuth2AuthorizedClientService authorizedClientService; public TokenEndpointController(OAuth2AuthorizedClientService authorizedClientService) { this.authorizedClientService = authorizedClientService; } @GetMapping public Map<String, String> getTokens() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient( "your-client-id", authentication.getName()); Map<String, String> tokens = new HashMap<>(); tokens.put("access_token", client.getAccessToken().getTokenValue()); tokens.put("id_token", client.getIdToken().getTokenValue()); return tokens; } }- 在网关中创建控制器,注入
- MVC应用在网关认证成功跳转回来后,调用该端点获取令牌,将其存储在自身的HttpSession中
- 后续MVC应用请求网关时,在请求头中携带
Authorization: Bearer {access_token},网关的TokenRelay过滤器会优先使用该令牌转发到下游服务
- 后续MVC应用请求网关时,在请求头中携带
方案2:认证成功跳转时携带加密令牌
自定义网关的OAuth2认证成功处理器,在跳转回MVC应用时将加密后的令牌通过Cookie传递(推荐):
- 实现
OAuth2AuthorizationSuccessHandler,处理认证成功后的逻辑:
@Component public class CustomAuthorizationSuccessHandler implements OAuth2AuthorizationSuccessHandler { private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); private final String mvcRedirectUrl = "http://mvc-app.com/callback"; private final TokenEncryptor tokenEncryptor; // 自定义加密工具类 @Override public void onAuthorizationSuccess(OAuth2AuthorizationSuccessEvent event) throws IOException { OAuth2AuthorizedClient client = event.getAuthorizedClient(); String encryptedAccessToken = tokenEncryptor.encrypt(client.getAccessToken().getTokenValue()); String encryptedIdToken = tokenEncryptor.encrypt(client.getIdToken().getTokenValue()); // 通过Cookie传递令牌 HttpServletResponse response = event.getResponse(); Cookie accessTokenCookie = new Cookie("access_token", encryptedAccessToken); accessTokenCookie.setHttpOnly(true); accessTokenCookie.setSecure(true); accessTokenCookie.setPath("/"); response.addCookie(accessTokenCookie); Cookie idTokenCookie = new Cookie("id_token", encryptedIdToken); idTokenCookie.setHttpOnly(true); idTokenCookie.setSecure(true); idTokenCookie.setPath("/"); response.addCookie(idTokenCookie); redirectStrategy.sendRedirect(event.getRequest(), response, mvcRedirectUrl); } }- 实现
- 在网关的OAuth2客户端配置中指定该处理器
- MVC应用从Cookie中提取加密令牌,解密后存储,后续请求时携带
方案3:基于Spring Session共享会话状态
如果MVC应用和网关处于同一域名下,可以通过Spring Session实现会话共享,直接复用网关的认证令牌:
- 网关和MVC应用都引入Spring Session依赖(比如
spring-session-data-redis),配置相同的会话存储(如Redis)
- 网关和MVC应用都引入Spring Session依赖(比如
- 网关认证成功后,OAuth2令牌信息会自动同步到共享会话中
- MVC应用可以从
HttpSession中直接获取令牌信息(需注意会话中存储的键名,可通过网关的OAuth2配置调整)
- MVC应用可以从
- 优势:无需额外开发,会话自动同步,安全性高;缺点:要求两者同域名,且会话存储一致
核心注意事项
- 安全性优先:令牌传输必须用HTTPS,Cookie需设置
HttpOnly和Secure属性,避免明文传递令牌 - 令牌过期处理:MVC应用需要监听令牌有效期,过期时可调用网关的令牌刷新端点(网关可暴露刷新接口,利用
OAuth2AuthorizedClientService刷新令牌) - TokenRelay兼容:无论采用哪种方案,网关的TokenRelay过滤器都会优先使用请求头中的令牌,若请求头无令牌则会 fallback到网关会话中的令牌,不影响原有逻辑
内容的提问来源于stack exchange,提问作者K. Siva Prasad Reddy
相关产品推荐
相关产品推荐

