使用OAuth2丢失会话的Spring安全性
我们有一个基于Spring引导的网关,使用Spring安全性、OAuth2登录和Zuul路由。它还使用Spring会话在Redis中存储会话。此网关在会话中存储OAuth2令牌,并将OAuth2承载令牌转发给后端服务 我们有一个用户经常被注销的问题。似乎这种情况大约每小时发生一次。我们甚至不太确定是什么原因导致了所有不同的工具到位 浏览器中的会话cookie将在更长的时间内过期。因此,我怀疑是Spring使会话无效,还是OAuth2令牌过期 通过对代码的快速检查,似乎使用OAuth2丢失会话的Spring安全性,spring,spring-boot,spring-security,spring-security-oauth2,Spring,Spring Boot,Spring Security,Spring Security Oauth2,我们有一个基于Spring引导的网关,使用Spring安全性、OAuth2登录和Zuul路由。它还使用Spring会话在Redis中存储会话。此网关在会话中存储OAuth2令牌,并将OAuth2承载令牌转发给后端服务 我们有一个用户经常被注销的问题。似乎这种情况大约每小时发生一次。我们甚至不太确定是什么原因导致了所有不同的工具到位 浏览器中的会话cookie将在更长的时间内过期。因此,我怀疑是Spring使会话无效,还是OAuth2令牌过期 通过对代码的快速检查,似乎OAuth2TokenRel
OAuth2TokenRelayFilter
支持刷新令牌。这是正确的吗
我们如何找出原因并加以解决
作为参考,我们使用以下版本:
- 弹簧靴2.1.12
- 格林威治春云酒店
@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
@Order(SecurityProperties.BASIC_AUTH_ORDER - 2)
@Profile("!security-disabled")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/login", "/login/**", "/favicon.ico").permitAll()
.antMatchers("/signout").authenticated()
.anyRequest().hasAnyRole("ADMIN", "MEMBER")
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.httpBasic()
.disable()
.formLogin()
.disable()
.logout()
.logoutUrl("/signout")
.deleteCookies("SESSION")
.and()
// @formatter:on
}
API路径的安全配置
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 2 - 10)
@Profile("!security-disabled")
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter
{
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.requestMatchers()
.antMatchers("/api/**")
.and()
.authorizeRequests()
.antMatchers("/**").hasAnyRole("ADMIN", "MEMBER")
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.headers()
.frameOptions().sameOrigin()
.and()
.httpBasic()
.disable()
.formLogin()
.disable()
.logout()
.disable()
.exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint());
// @formatter:on
}
}
更新
我们已经对Spring内部进行了一些调试。首先,我们发现缺少一个OAuth2RestTemplate
。根据,我们找到了如何将其添加到:
@Bean
public OAuth2RestTemplate oauth2RestTemplate(
OAuth2ClientContext oauth2ClientContext,
OAuth2ProtectedResourceDetails details)
{
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
当OAuth2TokenRelayFilter
调用restemplate.getAccessToken().getValue()时,这将引发异常代码>
需要重定向以获得用户批准
此异常是从中引发的。OAuth2TokenRelayFilter
OAuth2TokenRelayFilter
是一个预类型过滤器,用于设置具有访问令牌和令牌类型的上下文,用于进一步的身份验证。它使用getAccessToken()
方法验证令牌,并以401状态的“无法获取有效访问令牌”进行响应
您可以检查令牌的有效性,并将刷新令牌正确配置为grant_type as refresh_token,因为当访问令牌过期时,客户端使用刷新令牌grant type将刷新令牌交换为访问令牌,从而允许客户端继续拥有有效的访问令牌,而无需与客户端进一步交互用户
如果要禁用OAuth2TokenRelayFilter,可以使用以下命令
zuul.OAuth2TokenRelayFilter.pre.disable=true
我想您使用的是传统的spring-security-oauth2?如果您想将SpringCloudGateway与新的SpringSecuritySupportforOAuth2客户端一起使用(包括刷新访问令牌),可能会有所帮助。此外,会话和访问令牌生存期应该是独立的。Webflux会话生存期可以这样管理,我们使用的是传统的spring-security-oauth2。因为我们当前的安全代码不支持webflux,所以我们还没有开始使用SpringCloudGateway。因此,我们仍然使用Zuul,我们确实希望使用OAuth2TokenRelayFilter(或者我们需要编写自己的)。我更新了原始帖子,提供了更多关于OAuth2TokenReayFilter正在做什么的信息。