【问题标题】:SSO using spring-security-oauth2 : Authentication Code never read使用 spring-security-oauth2 的 SSO:从未读取身份验证代码
【发布时间】:2015-04-14 22:54:13
【问题描述】:

使用:

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

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

我已将我的客户端配置为使用 authorization_code 授权类型。

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

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

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

我已经能够通过修改OAuth2ClientAuthenticationProcessingFilter 来读取请求并在AccessTokenRequest 中设置授权码来使其工作。这是sn-p:

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() 方法(我最初的问题中有错误)。但我挖掘了更多,我意识到这不是问题。

我可以断言 OAuth2ClientContextFilterOAuth2ClientAuthenticationProcessingFilter 之前被调用(我用调试器检查过)。

我发现了什么,但不知道是否正常:

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')}");

这可以解释我从未从请求中读取授权码的问题。我在最初的问题中提到的 hack 只是推迟了问题。现在我收到 csrf 保护错误,因为当我认为一旦获得访问令牌后,AccessTokenRequest 就不再需要它时,AccessTokenRequest 总是会记住一些 stateKey

再次,也许我只是误解了洞的想法,所以请随时告诉我:)

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

【问题讨论】:

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


    【解决方案1】:

    您需要一个OAuth2ClientContextFilter,并且它需要在身份验证处理过滤器之前触发(它基本上完成了您在自定义过滤器中的内容)。我无法从您发布的代码中判断您是否有一个并且它没有触发或者您没有。

    【讨论】:

    • 我有。我也很难说这是 OAuth2ClientContextFilter 的工作,但是查看该类的代码,似乎对请求中的授权代码没有做任何事情。我可以看到它处理“redirect_uri”(“currentUri”),但不处理身份验证代码:(。正如我所说,我在 spring-security-oauth 中找不到 org.springframework.security.oauth2.client.token。调用 AccessTokenRequest.getAuthorizationCode()。感谢您的帮助。我的配置是一个 xml 配置,就像 here
    【解决方案2】:

    对于所有花费宝贵时间来帮助我的人,我们深表歉意。我非常专注于调试,以至于错过了一个配置问题。 不要像这样配置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

    【讨论】:

      猜你喜欢
      • 2017-06-14
      • 1970-01-01
      • 2014-09-15
      • 2019-01-28
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 2016-01-05
      相关资源
      最近更新 更多