Spring升级后baseUrl解析变更致OAuth2登录失败问题排查
Spring Cloud Gateway OAuth2 redirect_uri 端口问题解决方案
一、{baseUrl}填充逻辑的变化
在Spring Cloud Hoxton(搭配Spring Boot 2.3.x)版本中,Spring Security OAuth2会优先从X-Forwarded-*等反向代理头信息中解析外部访问的域名、端口,生成不带内部端口的baseUrl。
升级到Spring Cloud 2021.0.x(Jubilee,搭配Spring Boot 2.7.x)后,默认的baseUrl解析逻辑改为直接使用ServerHttpRequest的原生URI信息。如果网关部署在反向代理(如Nginx)之后,且未配置反向代理头的解析支持,Spring Security会读取网关自身的监听端口,导致生成的redirect_uri多了内部端口,触发授权服务器的校验失败。
二、正确配置redirect_uri的几种方法
1. 配置反向代理头解析(推荐)
如果网关在反向代理后运行,需开启Spring对X-Forwarded-*头的解析:
server: forward-headers-strategy: framework tomcat: remoteip: remote-ip-header: X-Forwarded-For protocol-header: X-Forwarded-Proto port-header: X-Forwarded-Port
同时确保反向代理服务器(如Nginx)正确传递这些头:
proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port;
配置完成后,Spring Security会自动解析外部访问的真实端口和域名,生成正确的redirect_uri。
2. 显式指定redirect_uri
放弃自动生成,直接在OAuth2客户端配置中硬编码或通过环境变量指定外部redirect_uri:
spring: security: oauth2: client: registration: your-client-id: redirect-uri: "https://your-external-domain/login/oauth2/code/your-client-id"
若需要动态适配环境,可结合Spring环境变量:
redirect-uri: "${EXTERNAL_DOMAIN}/login/oauth2/code/your-client-id"
3. 自定义redirect_uri生成逻辑
如果以上方案不适用,可通过自定义OAuth2AuthorizationRequestResolver手动控制redirect_uri的生成:
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class OAuth2Config { @Bean public OAuth2AuthorizationRequestResolver customAuthorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository) { DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, "/oauth2/authorization"); resolver.setAuthorizationRequestCustomizer(authorizationRequest -> { // 从环境变量或请求头获取外部地址,替换为实际业务逻辑 String externalRedirectUri = System.getenv("EXTERNAL_REDIRECT_URI"); authorizationRequest.redirectUri(externalRedirectUri); }); return resolver; } }
内容的提问来源于stack exchange,提问作者EdH
相关产品推荐
相关产品推荐

