使用OAuth2丢失会话的Spring安全性

使用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

我们有一个基于Spring引导的网关,使用Spring安全性、OAuth2登录和Zuul路由。它还使用Spring会话在Redis中存储会话。此网关在会话中存储OAuth2令牌,并将OAuth2承载令牌转发给后端服务

我们有一个用户经常被注销的问题。似乎这种情况大约每小时发生一次。我们甚至不太确定是什么原因导致了所有不同的工具到位

浏览器中的会话cookie将在更长的时间内过期。因此,我怀疑是Spring使会话无效,还是OAuth2令牌过期

通过对代码的快速检查,似乎
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正在做什么的信息。