引自免费微信小程序:皆我百晓生
在您的场景中,您遇到了SpringCloud、SpringSecurityOauth2和Gateway结合使用时的一个问题,即在OAuth2授权流程中,ExceptionTranslationFilter
类在处理/oauth2/authorize
请求时缓存的HttpServletRequest
对象与登录成功后TenantAuthenticationSuccessHandler
回调onAuthenticationSuccess
方法中获取到的请求对象不一致,从而导致无法正确重定向。
首先,我们需要理解Spring Security OAuth2的授权码模式工作流程:
- 用户访问受保护资源时,被重定向到
/oauth2/authorize
端点。 ExceptionTranslationFilter
捕获未认证异常,并通过sendStartAuthentication
方法将请求缓存以便后续登录成功后的重定向。- 用户登录并验证成功后,认证信息被传递给
TenantAuthenticationSuccessHandler
。 TenantAuthenticationSuccessHandler
尝试从缓存中获取原始请求(SavedRequest
),但由于某种原因获取的是不同的请求对象,因此无法正确执行重定向逻辑。
对于这个现象,可能的原因及排查步骤如下:
- 过滤器链顺序问题:确保
ExceptionTranslationFilter
在前置过滤器链中的位置正确,确保其在用户认证前能正确保存请求。 - 请求代理问题:由于使用了Gateway,可能存在代理转发过程中新的
HttpServletRequest
对象被创建的情况。检查 Gateway 配置是否正确地传递原始请求上下文到安全服务。 - 跨上下文问题:若资源服务器和安全服务器部署在不同上下文中,可能会造成请求对象的丢失。确保在跨上下文调用时,请求信息得到妥善保留和传递。
- 请求缓存实现:查看
HttpSessionRequestCache
或其他自定义实现是否存在问题,确保请求被正确缓存并在成功认证后恢复。
解决办法:
-
确保ExceptionTranslationFilter
和TenantAuthenticationSuccessHandler
都在正确的Spring Security Filter Chain中,并且按照预期顺序执行。
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(exceptionTranslationFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
.successHandler(tenantAuthenticationSuccessHandler())
// 其他配置...
}
@Bean
public ExceptionTranslationFilter exceptionTranslationFilter() {
// 初始化并返回ExceptionTranslationFilter实例
}
@Bean
public TenantAuthenticationSuccessHandler tenantAuthenticationSuccessHandler() {
// 初始化并返回TenantAuthenticationSuccessHandler实例
}
}
-
对于Gateway的配置,确保在转发请求到安全服务器时保持原始请求的完整性。可以考虑使用PreserveHostHeaderGlobalFilter
等过滤器,或者在路由配置中设置preserve_host_header
为true
(根据实际Gateway版本)。
-
检查TenantAuthenticationSuccessHandler
的初始化过程,确保使用的RequestCache
是同一个实例,例如确保共享同一HttpSession
。
通过以上排查和调整,应该可以解决SpringSecurityOauth2登录前后request不一致的问题,从而保证登录成功后能正确重定向。