我可以在 Spring
RelayState
通过 SAML 1
访问 SAMLCredential
来获得 SecurityContext
。
SAMLCredential saml = (SAMLCredential) SecurityContextHolder.getContext()
.getAuthentication().getCredentials();
String relay = saml.getRelayState();
如何使用
RelayState
在控制器方法中访问 SAML2
?
所以经过大量的搜索和反复试验,我想出了一种方法(尽管我真的相信它应该更简单)。
@Bean
Saml2AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationResolver registrations) {
OpenSaml4AuthenticationRequestResolver authenticationRequests = new OpenSaml4AuthenticationRequestResolver(registrations);
return new Saml2AuthenticationRequestResolver() {
public <T extends AbstractSaml2AuthenticationRequest> T resolve(HttpServletRequest request) {
T post = authenticationRequests.resolve(request);
String relayState = request.getParameter("RelayState");
log.info("@Config - RelayState is {}", relayState);
if (relayState != null)
{
HttpSession session = request.getSession();
session.setAttribute("RelayState", relayState);
log.info("@Config - RelayState saved to session");
}
return post;
}
};
}
然后在控制器方法中,您将按如下方式检索它:
public String index(Model model, @AuthenticationPrincipal Saml2AuthenticatedPrincipal principal, HttpServletRequest request) {
String username = principal.getName();
log.info("@Controller - Current Authenticated user: {}", username);
model.addAttribute("username", username);
HttpSession session = request.getSession();
String relayState = (String) session.getAttribute("RelayState");
log.info("@Controller - RelayState: {}", relayState);
if(relayState != null) {
session.removeAttribute("RelayState"); // prevent replay
return "redirect:"+relayState;
}
return "index";
}
基本上,您无法直接从控制器中的 HttpServletRequest 直接获取 RelayState 参数,因为初始 SAML 请求是经过处理和验证的 POST,然后生成 GET 并重定向到控制器。第二个请求不包含第一个请求的请求参数。