Nic*_*Wet 4 spring-security wso2is spring-boot spring-security-oauth2 spring-cloud
作为上下文,我一直在尝试获得一个相当简单的 @SprintBootApplication,其中包含一个附加的 @EnableOAuth2Sso 注释,并且与 WSO2 Identity Server 集成了很长一段时间。
在我看来,让这个工作应该是一个配置问题(正如在Spring Cloud Security上所宣传的那样) - 但到目前为止我没有运气。
为了了解发生了什么,我使用调试器逐步执行 spring-security-oauth2 代码以找出发生了什么。这样做时,我注意到我的 AccessTokenRequest 的 PreservedState 永远为空,并产生与 CSRF 相关的 InvalidRequestException。这是相关代码:
public class AuthorizationCodeAccessTokenProvider extends OAuth2AccessTokenSupport implements AccessTokenProvider {
....
private MultiValueMap<String, String> getParametersForTokenRequest(AuthorizationCodeResourceDetails resource,
AccessTokenRequest request) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.set("grant_type", "authorization_code");
form.set("code", request.getAuthorizationCode());
Object preservedState = request.getPreservedState();
if (request.getStateKey() != null || stateMandatory) {
// The token endpoint has no use for the state so we don't send it back, but we are using it
// for CSRF detection client side...
if (preservedState == null) {
throw new InvalidRequestException(
"Possible CSRF detected - state parameter was required but no state could be found");
}
}
Run Code Online (Sandbox Code Playgroud)
当涉及到上述代码时,我在使用 admin/admin 登录并且我的 Web 应用程序已收到身份验证代码后批准了声明:
http://localhost:9998/loginstate=Uu8ril&code=20ffbb6e4107ce3c5cf9ee22065f4f2
Run Code Online (Sandbox Code Playgroud)
鉴于我首先需要做的就是让登录部分工作,我尝试禁用 CSRF,但无济于事。
相关配置如下:
spring:
profiles: default
security:
oauth2:
client:
accessTokenUri: https://localhost:9443/oauth2/token
userAuthorizationUri: https://localhost:9443/oauth2/authorize
clientId: yKSD9XwET9XJ3srGEFXP6AfHhAka
clientSecret: zuPTcdJH435h3wgl055XNZ5ffNMa
scope: openid
clientAuthenticationScheme: header
resource:
userInfoUri: https://localhost:9443/oauth2/userinfo?schema=openid
Run Code Online (Sandbox Code Playgroud)
就我自己的调查工作而言,令人担忧的是 DefaultOAuthClientContext保留状态在需要使用之前被清除,这似乎是一个排序问题。
我正在使用最新版本的 Spring Boot (1.3.0) 和 WSO2 Identity Server (5.0)。还使用 spring-security-oauth 2.0.8。
事实证明,在提供的代码部分中引用的preservedState 为null 的原因是正在创建bean Oauth2ClientContext 的新实例,这正是不应该发生的事情——OAuth2ClientContext 的全部目的是存储状态。就 OAuth2 协议 ( RFC 6749 ) 而言,保留状态对于防止跨站点请求伪造很重要(请参阅第 10.12 节)。
选择这一点很简单,即启用调试日志记录并将针对 WSO2 IS 生成的输出与通过工作示例看到的内容进行比较。在我的情况下,我总是返回的工作示例是 Spring 团队自己提供的示例。
这是客户端配置(application.yml),然后使用 Spring 团队 SSO 服务器进行日志输出测试:
spring:
profiles: default
security:
oauth2:
client:
accessTokenUri: http://192.168.0.113:32768/uaa/oauth/token
userAuthorizationUri: http://192.168.0.113:32768/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnGp/Q5lh0P8nPL21oMMrt2RrkT9AW5jgYwLfSUnJVc9G6uR3cXRRDCjHqWU5WYwivcF180A6CWp/ireQFFBNowgc5XaA0kPpzEtgsA5YsNX7iSnUibB004iBTfU9hZ2Rbsc8cWqynT0RyN4TP1RYVSeVKvMQk4GT1r7JCEC+TNu1ELmbNwMQyzKjsfBXyIOCFU/E94ktvsTZUHF4Oq44DBylCDsS1k7/sfZC2G5EU7Oz0mhG8+Uz6MSEQHtoIi6mc8u64Rwi3Z3tscuWG2ShtsUFuNSAFNkY7LkLn+/hxLCu2bNISMaESa8dG22CIMuIeRLVcAmEWEWH5EEforTg+QIDAQAB
-----END PUBLIC KEY-----
id: openid
serviceId: ${PREFIX:}resource
Run Code Online (Sandbox Code Playgroud)
请注意,没有提到OAuth2ClientContext的创建。
DEBUG o.s.security.web.FilterChainProxy - /login?code=9HLSpP&state=G9kpy3 at position 6 of 12 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/login'
DEBUG o.s.s.o.c.f.OAuth2ClientAuthenticationProcessingFilter - Request is to process authentication
INFO o.s.s.o.c.DefaultOAuth2ClientContext - Getting access token request
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'scopedTarget.accessTokenRequest'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'scopedTarget.accessTokenRequest'
INFO o.s.s.o.client.OAuth2RestTemplate - Longer lived state key: G9kpy3
INFO o.s.s.o.client.OAuth2RestTemplate - Removing preserved state in oauth2context
INFO o.s.s.o.c.DefaultOAuth2ClientContext - Found preserved state: http://localhost:9999/login
Run Code Online (Sandbox Code Playgroud)
这是客户端配置 (application.yml),然后使用 WSO2IS 5.0.0 进行日志输出测试:
spring:
profiles: wso2
server:
port: 9998
security:
oauth2:
client:
accessTokenUri: https://localhost:9443/oauth2/token
userAuthorizationUri: https://localhost:9443/oauth2/authorize
clientId: yKSD9XwET9XJ3srGEFXP6AfHhAka
clientSecret: zuPTcdJH435h3wgl055XNZ5ffNMa
scope: openid
clientAuthenticationScheme: header
resource:
userInfoUri: https://localhost:9443/oauth2/userinfo?schema=openid
Run Code Online (Sandbox Code Playgroud)
请注意与创建 bean 'scopedTarget.oauth2ClientContext' 实例的行。
DEBUG o.s.security.web.FilterChainProxy - /login?state=PWhQwv&code=372ff0c197a4c85a0caf070cc9a6678 at position 6 of 12 in additional filter chain; firing Filter: 'OAuth2ClientAuthenticationProcessingFilter'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/login'
DEBUG o.s.s.o.c.f.OAuth2ClientAuthenticationProcessingFilter - Request is to process authentication
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'scopedTarget.oauth2ClientContext'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration$SessionScopedConfiguration$ClientContextConfiguration'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'scopedTarget.oauth2ClientContext'
INFO o.s.s.o.c.DefaultOAuth2ClientContext - Getting access token request
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'scopedTarget.accessTokenRequest'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'scopedTarget.accessTokenRequest'
INFO o.s.s.o.client.OAuth2RestTemplate - Longer lived state key: PWhQwv
INFO o.s.s.o.client.OAuth2RestTemplate - Removing preserved state in oauth2context
INFO o.s.s.o.c.DefaultOAuth2ClientContext - Found preserved state: null
Run Code Online (Sandbox Code Playgroud)
最后,下一个调用端口自然是确定为什么 OAuth2ClientContext 不是使用 WSO2 IS 配置创建的。调查表明,这是因为 WSO2 IS 没有传回预期的 JSESSIONID,因此找不到会话范围的 OAuth2ClientContext。
如果不顾一切地解决这种情况,一个潜在的黑客是克隆 Spring OAuth 2 并执行以下操作:
在 AuthorizationCodeAccessTokenProvider 类中,使用 hack 来更改请求中的保留状态。
private MultiValueMap<String, String> getParametersForTokenRequest(AuthorizationCodeResourceDetails resource,
AccessTokenRequest request) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.set("grant_type", "authorization_code");
form.set("code", request.getAuthorizationCode());
request.setPreservedState("http://localhost:9998/login");
Object preservedState = request.getPreservedState();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6045 次 |
| 最近记录: |