提问者:小点点

Spring SecurityOAuth2示例中的缺陷:用于多个提供程序的相同OAuth2ClientContext


我尝试用Spring Security实现OAuth2,并在以下Github中研究了Spring提供的示例:https://github.com/spring-projects/spring-security-oauth/blob/master/samples/oauth2/tonr/src/main/java/org/springframework/security/oauth/examples/config/WebMvcConfig.java

此OAuth2示例分为两个项目:

  • tonr:OAuth2客户端(OAuth2Client)和
  • sparklr:OAuth2提供程序(ResourceServer

Tonr允许显示来自Sparklr的照片,还包括一个脸书API客户端来列出一个账户的朋友。似乎一旦从一个提供商那里获得,相同的令牌就会发送到所有OAuth2提供商,即使令牌不是来自被调用的提供商。

步骤:

  • 我登录tonr2(localhost:8080/tonr2/login.jsp)
  • 我去Sparklr的照片,并登录sparklr2(localhost:8080/tonr2/sparklr/photos

sparklr令牌被发送到Facebook(在调试日志中可见),显然Facebook返回了400错误请求错误。

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

问题:如何分离OAuth2ClientContext以将令牌保留在其各自的资源服务器中?

我试图为facebookRestTemplate实例化不同的OAuth2ClientContext bean,但OAuth2流被破坏:

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

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

共1个答案

匿名用户

我也有同样的问题。我和你一样解决了它,除了你应该:

  1. 在DefaultOAuth2ClientContext的构造函数中注入AccessTokenRequest(请求范围)。(@在Spring的这个版本中需要资源注入,因为AccessTokenRequest是一个Map)。
  2. session-范围您的facebookClientContext不在不同用户之间共享令牌。

请参阅OAuth2ClientConfiguration作为指南。

修改您的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);
    }