spring-security - 在Redis中使用 spring 會話和 spring 雲安全性時,OAuth2ClientContext ( Spring Security oauth2 ) 不會持久化

  显示原文与译文双语对照的内容
0 0

感謝閱讀這個問題。

設置

我用的是:

  • spring-security-oauth2:2.0.7.RELEASE
  • spring-cloud-security:1.0.1.RELEASE
  • spring-session:1.0.1.RELEASE

對於在一個 Single-Sign-On ( @EnableOAuth2Sso ) 中使用 spring-session ( 通過 @EnableRedisHttpSession )的spring-security-oauth2OAuth2ClientContext 中的持久性,反向代理( @EnableZuulProxy ) 網關會有一個問題。

問題

在我看來,SessionScoped JdkDynamicAopProxied DefaultOAuth2ClientContextorg.springframework.cloud.security.oauth2.client.OAuth2ClientAutoConfiguration 未正確保存在Redis數據存儲中。


@Configuration
@ConditionalOnBean(OAuth2SsoConfiguration.class)
@ConditionalOnWebApplication
protected abstract static class SessionScopedConfiguration extends BaseConfiguration {

 @Bean
 @Scope(value ="session", proxyMode = ScopedProxyMode.INTERFACES)
 public OAuth2ClientContext oauth2ClientContext() {
 return new DefaultOAuth2ClientContext(accessTokenRequest);
 }

}

調試不使用的OAuth2ClientContext的創建表明,在每個客戶端會話中,bean將被實例化,並存儲在 HttpSession 上。 這裡實例將被重用,以存儲提取的in bearerToken 細節,除了存儲 spring SecurityContext 中的in accessTokenorg.springframework.security.core.Authentication

但是,一旦使用 @EnableRedisHttpSessionOAuth2ClientContext bean將首先在會話創建上創建,但後面還會創建( 同時使用相同的客戶端會話) 。 調試Redis客戶端會話內容確認 OAuth2ClientContext 無法被會話創建正確保存:

在檢索 OAuth2 bearerToken ( 沒有 SpringContext,沒有 scopedTarget.oauth2ClientContext ) 之前:


~$ redis-cli hkeys"spring:session:sessions:17c5e80b-390c-4fd6-b5f9-a6f225dbe8ea"
1)"maxInactiveInterval"
2)"sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
3)"lastAccessedTime"
4)"creationTime"
5)"sessionAttr:SPRING_SECURITY_SAVED_REQUEST"

檢索 OAuth2 bearerToken ( SpringContext持久化,但沒有 scopedTarget.oauth2ClientContext ) 后:


~$ redis-cli hkeys"spring:session:sessions:844ca2c4-ef2f-43eb-b867-ca6b88025c8b"
1)"sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
2)"lastAccessedTime"
3)"creationTime"
4)"sessionAttr:SPRING_SECURITY_LAST_EXCEPTION"
5)"sessionAttr:SPRING_SECURITY_CONTEXT"
6)"maxInactiveInterval"

如果我們現在嘗試訪問一個 configurer Zuul 路由( 因此需要調用 org.springframework.security.oauth2.client.DefaultOAuth2ClientContext#getAccessToken ( ),將創建另一個 OAuth2ClientContext 實例,因為不在Redis中持久化,使用 nullaccessToken

Funnily足夠,這個實例稍後將在 Redis ( 但是 null 實例是持久化的,因為不要求使用 accessToken ) 中持久化:


~$ redis-cli hkeys"spring:session:sessions:c7120835-6709-4c03-8d2c-98f830ed6104"
1)"sessionAttr:org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
2)"sessionAttr:SPRING_SECURITY_LAST_EXCEPTION"
3)"sessionAttr:scopedTarget.oauth2ClientContext"
4)"sessionAttr:SPRING_SECURITY_CONTEXT"
5)"maxInactiveInterval"
6)"creationTime"
7)"lastAccessedTime"
8)"sessionAttr:org.springframework.web.context.request.ServletRequestAttributes.DESTRUCTION_CALLBACK.scopedTarget.oauth2ClientContext" 

創建一個簡單的ScopedProxyMode.TARGET_CLASS 注入 bean,就像預期的那樣,bean在Redis中保持正確。


public class HelloWorldService implements Serializable {

 public HelloWorldService(){
 System.out.println("HelloWorldService created");
 }

 private String name ="World";

 public String getName(){
 return name;
 }

 public void setName(String name){
 this.name=name;
 }

 public String getHelloMessage() {
 return"Hello" + this.name;
 }
}

@Configuration
public class AppConfig {

 private SecureRandom random = new SecureRandom();

 @Bean
 @Scope(value ="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
 public HelloWorldService myHelloService(){
 HelloWorldService s = new HelloWorldService();
 String name = new BigInteger(130, random).toString(32);
 System.out.println("name =" + name);
 s.setName(name);
 System.out.println("Resource HelloWorldService created =" + s);
 return s;
 }
}

例子

通過添加以下依賴項,可以在 @dave-syer 示例中複製 OAuth2反向代理網關插件中所描述的問題:


<dependency>
 <groupId>org.springframework.session</groupId>
 <artifactId>spring-session</artifactId>
 <version>1.0.1.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

以及 UiApplication 中的@EnableRedisHttpSession 註釋。

問題

我們應該忽略 org.springframework.cloud.security.oauth2.client.OAuth2ClientAutoConfiguration 從自動配置和手動創建具有不同設置的OAuth2ClientContext 以啟用Redis中的spring-session 持久性? 如果是這樣,你能提供一個例子?

否則:如何在Redis中保持 OAuth2ClientContext

許多人提前閱讀這個問題,試圖幫助。

时间: 原作者:

0 0

@dave-syer 提示正確。

我在此發布了可以用於設置 RequestContextFilter 並啟用 spring-security-oauth 對象 spring-session 持久性的配置。 如果這可以幫助某人。


@Configuration
public class RequestContextFilterConfiguration {

 @Bean
 @ConditionalOnMissingBean(RequestContextFilter.class)
 public RequestContextFilter requestContextFilter() {
 return new RequestContextFilter();
 }

 @Bean
 public FilterRegistrationBean requestContextFilterChainRegistration(
 @Qualifier("requestContextFilter") Filter securityFilter) {
 FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
 registration.setOrder(SessionRepositoryFilter.DEFAULT_ORDER + 1);
 registration.setName("requestContextFilter");
 return registration;
 }
}

原作者:
...