使用:
我有一个使用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非常相似。
答案 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