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;
 }
}

原作者:
...