SSO使用spring-security-oauth2:身份验证代码永远不会读取

时间:2015-04-09 14:00:48

标签: java spring-security spring-security-oauth2

使用:

  • spring-security 3.2.5
  • spring-security-oauth 2.0.7

我有一个使用spring-security-oauth(oauth2)构建的oauth2提供程序。

我在其中配置了我的客户端以使用authorization_code授权类型。

提供商完美运作: 使用curl进行测试,我可以获得授权代码并将其交换为访问令牌。 所以在服务提供商部分,一切都很好。

现在我尝试使用spring-security-oauth来实现客户端应用程序。 我使用xml配置,强烈基于示例here,但使用我自己的提供商(上面提到)而不是谷歌。

当我在客户端上调用受保护资源时,OAuth2ClientAuthenticationProcessingFilter会尝试获取访问令牌,因此会重定向到我的服务提供商。那个强制用户按预期登录,然后将他重定向到配置的redirect_uri(重定向uri是为OAuth2ClientAuthenticationProcessingFilter配置的重定向:类似http://myClient/context/external/login)。 问题是:客户端从不读取服务提供商返回的请求中的授权代码。因此OAuth2ClientAuthenticationProcessingFilter重新启动流程,要求提供授权码。

我已经能够通过修改OAuth2ClientAuthenticationProcessingFilter来阅读请求并在AccessTokenRequest中设置授权代码来使其工作。这是片段:

OAuth2AccessToken accessToken;
try {
  String code = request.getParameter("code");
  if(code != null) {
    restTemplate.getOAuth2ClientContext().getAccessTokenRequest().setAuthorizationCode(code);
  }
  accessToken = restTemplate.getAccessToken();
  ...

在尝试此操作之前,我尝试制作一个"调用层次结构"在方法org.springframework.security.oauth2.client.token.AccessTokenRequest.setAuthorizationCode()上,找到代码spring中调用方法的位置,但它没有返回任何内容。

这是一个错误吗? 我真的不想用自己的OAuth2ClientAuthenticationProcessingFilter替换它。

是否有人使其成功(在该版本或其他版本中)?

更新

它是从未调用的setAuthorizationCode()方法(我的初始问题中的错误)。但我挖了一点,我意识到这不是问题。

我可以断言在OAuth2ClientContextFilter之前调用OAuth2ClientAuthenticationProcessingFilter(我用调试器检查了它)。

我找到了什么,但不知道这是否正常:

DefaultAccessTokenRequest的默认构造函数只调用一次:在应用程序启动时。从不调用另一个构造函数(参与参数的映射)。由于我在RestTemplateBeanDefinitionParser中看到访问令牌请求的作用域是“请求”,我希望构造函数在每个新的http请求中调用参数的映射到我的客户端应用程序 在RestTemplateBeanDefinitionParser

BeanDefinitionBuilder request = BeanDefinitionBuilder.genericBeanDefinition(DefaultAccessTokenRequest.class);
request.setScope("request");
request.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
request.addConstructorArgValue("#{request.parameterMap}");
request.addPropertyValue("currentUri", "#{request.getAttribute('currentUri')}");

这可以解释我的授权代码永远不会从请求中读取的问题。我在最初的问题中提到的黑客只是推迟了问题。现在我得到了csrf保护错误,因为{I}假设一旦我获得访问令牌就不再需要AccessTokenRequest总是会记住一些stateKey

再说一次,也许我只是误解了这个漏洞,所以请随时告诉我:)

我没有发布我的配置,因为它与that one here非常相似。

2 个答案:

答案 0 :(得分:1)

您需要一个OAuth2ClientContextFilter,它需要在身份验证处理过滤器之前启动(它基本上会在您的自定义过滤器中执行此操作)。我不能从您发布的代码中判断出来,如果您有一个代码并且它没有触发,或者您没有代码。

答案 1 :(得分:0)

对不起那些花费宝贵时间试图帮助我的人。我是如此专心调试,我错过了一个配置问题。 永远不要像这样配置Oauth2RestTemplate

<beans:bean id="myRestTemplate" class="org.springframework.security.oauth2.client.OAuth2RestTemplate">
     <beans:constructor-arg ref="myResourceId"/>
</beans:bean>

这解释了为什么DefaultAccessTokenRequest不是请求作用域,因此它调用了默认控制器而不是一个接收请求的参数映射。 不要喜欢我并使用xml命名空间! :

<oauth:rest-template id="myRestTemplate" resource="myResourceId"/>

仍然想知道我为什么这样做:P