Spring 安全 SAML SSO 重定向到控制器
Spring Security SAML SSO redirect to controller
在 IdP 启动的设置中使用代码片段重定向到控制器 (/bootstrap/v1):
public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successRedirectHandler.setDefaultTargetUrl("/bootstrap/v1");
return successRedirectHandler;
}
控制器代码片段:
public class BootstrapController extends ParentController {
@RequestMapping(value = "/v1", method = RequestMethod.POST)
public ResponseEntity<BootstrapResponseDto> bootstrap(@RequestBody BootstrapRequestDto bootstrapRequestDto, @RequestHeader(value = "MAC-ADDRESS", required = false) String macAddress) {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new BootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
}
调试级别日志片段:
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d
ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 INFO
http-nio-8080-exec-6 Spring Security Debugger:
Request received for POST '/saml/SSO':
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper@28cc5b21
servletPath:/saml/SSO pathInfo:null headers: host: localhost:8080
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0)
Gecko/20100101 Firefox/63.0 accept:
text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
accept-language: en-US,en;q=0.5 accept-encoding: gzip, deflate
content-type: application/x-www-form-urlencoded content-length: 11320
dnt: 1 connection: keep-alive cookie:
JSESSIONID=ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2
upgrade-insecure-requests: 1
Security filter chain: [ MetadataGeneratorFilter
WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter
CustomLogFilter HeaderWriterFilter LogoutFilter
UsernamePasswordAuthenticationFilter BasicAuthenticationFilter
FilterChainProxy RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter SessionManagementFilter
ExceptionTranslationFilter FilterSecurityInterceptor ]
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d INFO
http-nio-8080-exec-6
o.o.c.b.s.SAMLProtocolMessageXMLSignatureSecurityPolicyRule:
Validation of protocol message signature succeeded, message type:
{urn:oasis:names:tc:SAML:2.0:protocol}Response 11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d
ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 INFO
http-nio-8080-exec-7 Spring Security Debugger:
Request received for GET '/bootstrap/v1':
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper@5f9e2aff
servletPath:/bootstrap/v1 pathInfo:null headers: host: localhost:8080
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0)
Gecko/20100101 Firefox/63.0 accept:
text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
accept-language: en-US,en;q=0.5 accept-encoding: gzip, deflate dnt: 1
connection: keep-alive cookie:
JSESSIONID=ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2
upgrade-insecure-requests: 1
Security filter chain: [ MetadataGeneratorFilter
WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter
CustomLogFilter HeaderWriterFilter LogoutFilter
UsernamePasswordAuthenticationFilter BasicAuthenticationFilter
FilterChainProxy RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter SessionManagementFilter
ExceptionTranslationFilter FilterSecurityInterceptor ]
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d WARN
http-nio-8080-exec-7 o.s.w.s.PageNotFound: Request method 'GET' not
supported
ExpiringUsernameAuthenticationToken 设置为 return:
org.springframework.security.providers.ExpiringUsernameAuthenticationToken@fee70636: Principal: com.<my-company>.security.authentication.@325fcf8b; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: authority_1, authority_2, authority_3, authority_4
所以,我猜我的 SAML 验证和用户身份验证和授权是好的。
看来我面临的问题是 HTTP GET 无法正常工作。
如何配置和提交 HTTP POST?要么
我是否应该重构我的控制器来处理行为(这可能会破坏基于表单的登录,这也是应用程序身份验证的一部分)?
HTTP Status 405 - Method Not Allowed Error
我认为这个问题与 SAML 完全无关,而是一个通用的 Spring 安全问题。此外,您没有指定正文 BootstrapRequestDto 的来源。
您有一个执行重定向的 SuccessHandler:
successRedirectHandler.setDefaultTargetUrl("/bootstrap/v1");
这执行 GET
而您的控制器只接受 POST
。而且你还没有说明那个尸体来自哪里?
您需要编写一个自定义成功处理程序来发出 post(javascript 自动提交表单?),或者只需更改您的控制器以也接受 GET。
public class BootstrapController extends ParentController {
@RequestMapping(value = "/v1", method = RequestMethod.GET)
public ResponseEntity<BootstrapResponseDto> bootstrap() {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new bootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
@RequestMapping(value = "/v1", method = RequestMethod.POST)
public ResponseEntity<BootstrapResponseDto> bootstrap(@RequestBody BootstrapRequestDto bootstrapRequestDto, @RequestHeader(value = "MAC-ADDRESS", required = false) String macAddress) {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new BootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
}
在 IdP 启动的设置中使用代码片段重定向到控制器 (/bootstrap/v1):
public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successRedirectHandler.setDefaultTargetUrl("/bootstrap/v1");
return successRedirectHandler;
}
控制器代码片段:
public class BootstrapController extends ParentController {
@RequestMapping(value = "/v1", method = RequestMethod.POST)
public ResponseEntity<BootstrapResponseDto> bootstrap(@RequestBody BootstrapRequestDto bootstrapRequestDto, @RequestHeader(value = "MAC-ADDRESS", required = false) String macAddress) {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new BootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
}
调试级别日志片段:
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 INFO http-nio-8080-exec-6 Spring Security Debugger:
Request received for POST '/saml/SSO':
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper@28cc5b21
servletPath:/saml/SSO pathInfo:null headers: host: localhost:8080 user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0) Gecko/20100101 Firefox/63.0 accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 accept-language: en-US,en;q=0.5 accept-encoding: gzip, deflate content-type: application/x-www-form-urlencoded content-length: 11320 dnt: 1 connection: keep-alive cookie: JSESSIONID=ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 upgrade-insecure-requests: 1
Security filter chain: [ MetadataGeneratorFilter
WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter
CustomLogFilter HeaderWriterFilter LogoutFilter
UsernamePasswordAuthenticationFilter BasicAuthenticationFilter
FilterChainProxy RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter SessionManagementFilter
ExceptionTranslationFilter FilterSecurityInterceptor ]
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d INFO http-nio-8080-exec-6 o.o.c.b.s.SAMLProtocolMessageXMLSignatureSecurityPolicyRule: Validation of protocol message signature succeeded, message type: {urn:oasis:names:tc:SAML:2.0:protocol}Response 11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 INFO http-nio-8080-exec-7 Spring Security Debugger:
Request received for GET '/bootstrap/v1':
org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper@5f9e2aff
servletPath:/bootstrap/v1 pathInfo:null headers: host: localhost:8080 user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0) Gecko/20100101 Firefox/63.0 accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 accept-language: en-US,en;q=0.5 accept-encoding: gzip, deflate dnt: 1 connection: keep-alive cookie: JSESSIONID=ZDJhMWExYWUtZTAxNy00NDQwLWJmOTctNzcyNTJlOWUyNmQ2 upgrade-insecure-requests: 1
Security filter chain: [ MetadataGeneratorFilter
WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter
CustomLogFilter HeaderWriterFilter LogoutFilter
UsernamePasswordAuthenticationFilter BasicAuthenticationFilter
FilterChainProxy RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter SessionManagementFilter
ExceptionTranslationFilter FilterSecurityInterceptor ]
11-29-2018 13:33:53 e7a5edb2-4051-4132-bad0-856d58af1c7d WARN http-nio-8080-exec-7 o.s.w.s.PageNotFound: Request method 'GET' not supported
ExpiringUsernameAuthenticationToken 设置为 return:
org.springframework.security.providers.ExpiringUsernameAuthenticationToken@fee70636: Principal: com.<my-company>.security.authentication.@325fcf8b; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: authority_1, authority_2, authority_3, authority_4
所以,我猜我的 SAML 验证和用户身份验证和授权是好的。
看来我面临的问题是 HTTP GET 无法正常工作。
如何配置和提交 HTTP POST?要么 我是否应该重构我的控制器来处理行为(这可能会破坏基于表单的登录,这也是应用程序身份验证的一部分)?
HTTP Status 405 - Method Not Allowed Error
我认为这个问题与 SAML 完全无关,而是一个通用的 Spring 安全问题。此外,您没有指定正文 BootstrapRequestDto 的来源。
您有一个执行重定向的 SuccessHandler:
successRedirectHandler.setDefaultTargetUrl("/bootstrap/v1");
这执行 GET
而您的控制器只接受 POST
。而且你还没有说明那个尸体来自哪里?
您需要编写一个自定义成功处理程序来发出 post(javascript 自动提交表单?),或者只需更改您的控制器以也接受 GET。
public class BootstrapController extends ParentController {
@RequestMapping(value = "/v1", method = RequestMethod.GET)
public ResponseEntity<BootstrapResponseDto> bootstrap() {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new bootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
@RequestMapping(value = "/v1", method = RequestMethod.POST)
public ResponseEntity<BootstrapResponseDto> bootstrap(@RequestBody BootstrapRequestDto bootstrapRequestDto, @RequestHeader(value = "MAC-ADDRESS", required = false) String macAddress) {
myAppUserDetails userDetails = SecurityContextUtils.getUserDetails();
BootstrapResponseDto bootstrapResponseDto = new BootstrapResponseDto();
// some app specific logic goes here...
return new ResponseEntity<>(bootstrapResponseDto, HttpStatus.OK);
}
}