Java Spring security OAuth2示例中存在缺陷:多个提供程序使用的OAuth2Client上下文相同

Java Spring security OAuth2示例中存在缺陷:多个提供程序使用的OAuth2Client上下文相同,java,spring,spring-security,oauth-2.0,Java,Spring,Spring Security,Oauth 2.0,我尝试使用Spring安全性实现OAuth2,并在以下Github中研究了Spring提供的示例: 此OAuth2示例分为两个项目: tonr:OAuth2客户端(OAuth2Client)和 Sparkr:OAuth2提供程序(ResourceServer和AuthorizationServer) Tonr允许显示Sparkr的照片,还包括一个Facebook API客户端,用于列出帐户的好友。 似乎一旦从一个提供者获得了相同的令牌,就会被发送到所有OAuth2提供者,即使该令牌不是来自

我尝试使用Spring安全性实现OAuth2,并在以下Github中研究了Spring提供的示例:

此OAuth2示例分为两个项目:

  • tonr:OAuth2客户端(OAuth2Client)和
  • Sparkr:OAuth2提供程序(ResourceServer和AuthorizationServer)
Tonr允许显示Sparkr的照片,还包括一个Facebook API客户端,用于列出帐户的好友。 似乎一旦从一个提供者获得了相同的令牌,就会被发送到所有OAuth2提供者,即使该令牌不是来自被调用的提供者

步骤:

  • 我登录到tonr2(localhost:8080/tonr2/login.jsp)
  • 我转到Sparkr照片并登录Sparkr2(localhost:8080/tonr2/sparkr/photos&localhost:8080/sparkr2/login.jsp)
  • 我批准阅读的范围,并看到照片:OK
  • 然后我进入Facebook好友页面:localhost:8080/tonr2/Facebook/info
sparkr令牌被发送到Facebook(在调试日志中可见),显然Facebook返回了一个400错误请求错误

如果现在,我从tonr注销,直接点击Facebook好友页面并再次登录tonr,它正在工作;向Facebook请求令牌并授予访问权限。 因此,相同的OAuth2ClientContext和相同的令牌从Sparkr保存到Facebook

问题: 如何分离OAuth2ClientContext以将令牌与其各自的资源服务器保持一致

我尝试为facebookRestTemplate实例化不同的OAuth2ClientContext bean,但OAuth2流因以下原因中断:

@Bean(name = "facebookClientContext")
public OAuth2ClientContext facebookClientContext() {
    return new DefaultOAuth2ClientContext();
}

@Bean
public OAuth2RestTemplate facebookRestTemplate(@Qualifier("facebookClientContext") OAuth2ClientContext clientContext) {
    ...

我也有同样的问题。我和你一样解决了这个问题,只是你应该:

  • 在DefaultOAuth2ClientContext的构造函数中注入AccessTokenRequest(请求范围)。(@资源注入在Spring的这个版本中是必需的,因为AccessTokenRequest是一个映射)
  • 会话将您的facebookClientContext范围限定为不在不同用户之间共享令牌
  • 请参见OAuth2Client配置作为指南

    修改WebMvcConfig$ResourceConfiguration:

        @Resource(name = "accessTokenRequest")
        private AccessTokenRequest accessTokenRequest;
    
        @Bean
        @Qualifier("facebookClientContext")
        @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
        public DefaultOAuth2ClientContext facebookClientContext() {
            return new DefaultOAuth2ClientContext(accessTokenRequest);
        }
    
        @Bean
        public OAuth2RestTemplate facebookRestTemplate(
                @Qualifier("facebookClientContext") OAuth2ClientContext clientContext) {
            OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), clientContext);
            MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            converter.setSupportedMediaTypes(
                    Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("text/javascript")));
            template.setMessageConverters(Arrays.<HttpMessageConverter<?>>asList(converter));
            return template;
        }
    
        @Bean
        public OAuth2RestTemplate sparklrRestTemplate(
                @Qualifier("oauth2ClientContext") OAuth2ClientContext clientContext) {
            return new OAuth2RestTemplate(sparklr(), clientContext);
        }
    
        @Bean
        public OAuth2RestTemplate sparklrRedirectRestTemplate(
                @Qualifier("oauth2ClientContext") OAuth2ClientContext clientContext) {
            return new OAuth2RestTemplate(sparklrRedirect(), clientContext);
        }
    
    @Resource(name=“accessTokenRequest”)
    私有AccessTokenRequest AccessTokenRequest;
    @豆子
    @限定符(“facebookClientContext”)
    @范围(value=“session”,proxyMode=ScopedProxyMode.INTERFACES)
    公共默认OAuth2Client上下文facebookClientContext(){
    返回新的DefaultOAuth2ClientContext(accessTokenRequest);
    }
    @豆子
    公共OAuth2RestTemplate facebookRestTemplate(
    @限定符(“facebookClientContext”)OAuth2ClientContext(客户端上下文){
    OAuth2RestTemplate=新的OAuth2RestTemplate(facebook(),clientContext);
    MappingJackson2HttpMessageConverter=新的MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(
    asList(MediaType.APPLICATION_JSON,MediaType.valueOf(“text/javascript”));
    setMessageConverters(数组)。