【发布时间】:2014-12-14 03:11:16
【问题描述】:
我在重定向到访问令牌入口点 /oauth/token 时遇到问题,详细信息如下。我希望有人能给我一些启发,因为我花了很多时间 实现这一点。
另外,有趣的是,即使按照他们的说明,我也无法使用 SoapUI 5.0 社区版进行测试。它获取授权代码,但稍后失败,因为您需要将重定向 URI 设置为“urn:ietf:wg:oauth:2.0:oob”。
由于 Spring-Security-Oauth2 缺乏很多好的文档,我花了很多时间调试和记录我决定分享的工作 我的 cmets 和配置代码在这里可能对其他人也有帮助。
我在我的 pom 上使用以下依赖版本:
<org.springframework-version>4.0.5.RELEASE</org.springframework-version>
<org.springframework.security-version>3.2.5.RELEASE</org.springframework.security-version>
<org.springframework.security.oauth2-version>2.0.3.RELEASE</org.springframework.security.oauth2-version>
现在,我们的想法是使用 Cassandra 作为持久性存储来实现所有 clientId 对象、UserPrincipal、访问、nonce 和令牌存储。所有这些组件 工作正常并经过测试。事实上,它获取所有的身份验证/授权,创建授权代码。
我最近在 Spring Oauth2 github 上测试 JDBC 存储时看到了一个错误,但这与测试而不是实际实现有关,特别是因为没有 使用 JDBC。
我编写了一个客户端 Web 应用程序来访问 REST 资源,该资源与 OAuth2 服务器和 Spring Security 一起用于登录。一切顺利,直到我请求 /oauth/token 的访问令牌。
当我首先点击安全的 Rest 服务时,它会正确地开始进行重定向,然后执行 DefaultOAuth2RequestFactory createAuthorizationRequest() 方法。负载 ClientDetails 对象与商店中的秘密等完美结合。因此它具有 Oauth2 客户端的所有范围、授权等。它还正确验证了 redirectURIParameter 并解决重定向。然后它转到 TokenStoreUserApprovalHandler 并创建 OAuth2Request 对象。然后,当然,尝试找到一个现有的访问令牌 工作流中尚不存在。它从 authenticationKeyGenerator 创建 authenticationkey 并查询此时正确返回 null 的存储。 然后它重定向回 /oauth/authorize 两次,第二次它有一个授权码并在approveOrDeny() 方法中标记为已批准(AuthorizationEndPoint)。 authorizationCodeServices 创建代码并将其正确存储在我的 Cassandra 存储中。
此时它调用 (AuthorizationEndPoint) getSuccessfulRedirect() 将状态参数添加到模板。
然后它调用(OAuth2RestTemplate 类)getAccessToken() 方法。由于访问令牌很好且有效,因此它调用acquireAccessToken(),它返回一个accessTokenRequest
{code=[Q19Y6u], state=[1PyzHf]} 。然后它调用accessTokenProvider 在obtainAccessToken() 获取访问令牌。然后调用OAuth2AccessTokenSupport
retrieveToken() 方法。并在getRestTemplate 失败。 AuthorizationCodeResourceDetails 是使用授权类型 authorization_code 完美创建的,它同时具有 authorizationScheme
和clientAuthenticationScheme 作为标题。 clientId 与 clientSecret 是正确的。 AuthorizationCodeResourceDetails 的 id 是 oAuth2ClientBean 和 userAuthorizationURI 是
http://myhost.com:8080/MyAPI/oauth/authorize。标题显示为
{Authorization=[Basic .....]}
提取器是org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport。
表格是{grant_type=[authorization_code], code=[Xc7yni], redirect_uri=[http://myhost.com:8080/OAuthClient/support]}
然后应用程序冻结并显示在日志中:
DEBUG: org.springframework.security.authentication.DefaultAuthenticationEventPublisher - No event was found for the exception org.springframework.security.authentication.InternalAuthenticationServiceException
DEBUG: org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.InternalAuthenticationServiceException
然后我的客户端 Web 应用程序出现以下异常:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is error="access_denied", error_description="Error requesting access token."
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
现在,我相信我的 OAuth2 和 Spring Security 的 xml 配置有一些问题。所以配置文件如下。
我确实有一些关于它的问题,所以首先是以下问题:
1) <oauth2:authorization-server> 我不确定我的配置是否正确。请查看我的 xml 文件中的 cmets。
我添加了指向我的 userAuthenticationManager bean(一个身份验证管理器)的 authorization-request-manager-ref 参数
它需要一个身份验证提供者 user-service-ref="userService"
<oauth2:authorization-server client-details-service-ref="webServiceClientService"
token-services-ref="tokenServices" user-approval-page="/oauth/userapproval"
error-page="/oauth/error" authorization-endpoint-url="/oauth/authorize"
token-endpoint-url="/oauth/token" user-approval-handler-ref="userApprovalHandler"
redirect-resolver-ref="resolver">
<oauth2:authorization-code
authorization-code-services-ref="codes" />
<oauth2:implicit/>
<oauth2:refresh-token/>
<oauth2:client-credentials/>
<oauth2:password authentication-manager-ref="userAuthenticationManager"/>
<!-- <oauth2:custom-grant token-granter-ref=""/> -->
</oauth2:authorization-server>
2) authentication-manager oauthClientAuthenticationManager 在“/oauth/token”被拦截时使用。 这定义如下:
<sec:authentication-manager id="oauthClientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService">
<sec:password-encoder ref="passwordEncoder" />
</sec:authentication-provider>
</sec:authentication-manager>
3) 我定义了以下在 sec:global-method-security 中使用的 methodSecurityExpressionHandler bean。 也不确定这是否正确。
<beans:bean id="methodSecurityExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler" />
4) 我还有一个我认为不推荐的 bean“clientCredentialsTokenEndpointFilter”。 我将其用作入口点“/oauth/token”的自定义过滤器,但我认为这是错误的。
<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="oauthClientAuthenticationManager"/>
</beans:bean>
A filter and authentication endpoint for the OAuth2 Token Endpoint. Allows clients to authenticate using request
parameters if included as a security filter, as permitted by the specification (but not recommended). It is
recommended by the specification that you permit HTTP basic authentication for clients, and not use this filter at
all.
5) 现在对于 Oauth 令牌端点: 这是端点 /oauth/token 因为我在这里有很多问题:
- 这是永远达不到的。
- 我是否应该有一个像
clientCredentialsTokenEndpointFilter这样的自定义过滤器? - 我必须有一个 http-basic 入口点吗?
- 我应该拥有
IS_AUTHENTICATED_FULLY中的访问属性,还是可以使用我在UserPrincipal对象上定义的权限,例如OAUTH_CLIENT我已经添加在那里? - 会话怎么样?我应该说“无国籍”还是 “从不”
- 我也应该添加
corsFilter吗? - 入口点是否正确?
OAuth2AuthenticationEntryPoint是哪个类? - 我必须添加 csrf 令牌吗?我相信不会 限制更多。
- 表达式处理程序作为
org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandle是否正确? - 我可以将 authentication-manager-ref 从
oauthClientAuthenticationManager更改为userAuthenticationManager。
<sec:http use-expressions="true" create-session="stateless"
authentication-manager-ref="userAuthenticationManager"
entry-point-ref="oauthAuthenticationEntryPoint" pattern="/oauth/token">
<sec:intercept-url pattern="/oauth/token" access="hasAuthority('OAUTH_CLIENT')" />
<!-- <sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> -->
<sec:http-basic entry-point-ref="oauthAuthenticationEntryPoint"/>
<!-- <sec:http-basic/> -->
<sec:anonymous enabled="false" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:expression-handler ref="webSecurityExpressionHandler" />
<!-- <sec:custom-filter ref="corsFilter" after="LAST"/> -->
</sec:http>
我想在这里添加完整的配置文件,但有一个限制。
【问题讨论】:
标签: spring spring-security spring-security-oauth2