我希望有人能给我一个比我在文档中找到的更具体的例子。
使用 SpringBoot/Spring Security 5.6.0。我正在将基于 SpringSecurity/SAML 的身份验证过程迁移到SAML2。
我需要将根据 responseToken 信息构建的 UserDetails 添加到身份验证中。类似于我们可以在文档中阅读的内容:https ://docs.spring.io/spring-security/reference/5.6.0-RC1/servlet/saml2/index.html#servlet-saml2login-opensamlauthenticationprovider-userdetailsservice
但我不明白第三点:返回包含用户详细信息的自定义身份验证:“return MySaml2Authentication(userDetails, authentication);”
在任何情况下,您都必须执行“return new MySaml2Authentication(userDetails, authentication);” 正确的?
在任何情况下,当进程继续时,它会被执行:
身份验证 authenticate = provider.authenticate(authentication);
正如我们所见,它将 Details 值替换为原始值。
authenticationResponse.setDetails(authentication.getDetails());
/**
* @param authentication the authentication request object, must be of type
* {@link Saml2AuthenticationToken}
* @return {@link Saml2Authentication} if the assertion is valid
* @throws AuthenticationException if a validation exception occurs
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
Saml2AuthenticationToken token = (Saml2AuthenticationToken) authentication;
String serializedResponse = token.getSaml2Response();
Response response = parse(serializedResponse);
process(token, response);
AbstractAuthenticationToken authenticationResponse = this.responseAuthenticationConverter
.convert(new ResponseToken(response, token));
if (authenticationResponse != null) {
authenticationResponse.setDetails(authentication.getDetails());
}
return authenticationResponse;
}
catch (Saml2AuthenticationException ex) {
throw ex;
}
catch (Exception ex) {
throw createAuthenticationException(Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR, ex.getMessage(), ex);
}
}
如何添加一个依赖于从令牌获得的信息的 UserDetails?我不能扩展 OpenSaml4AuthenticationProvider 因为它是"final"。
并在 MySaml2AuthenticationManager 中设置 Details 后执行Authentication authenticate = provider.authenticate(authentication); 但这对我来说似乎不对。
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
OpenSaml4AuthenticationProvider provider = new OpenSaml4AuthenticationProvider();
provider.setResponseAuthenticationConverter(responseToken -> {
Saml2Authentication auth = OpenSaml4AuthenticationProvider
.createDefaultResponseAuthenticationConverter()// First, call the default converter, which extracts attributes and authorities from the response
.convert(responseToken);
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
String role = getRole(auth.getName());
grantedAuthorities.add(new SimpleGrantedAuthority(role));
Saml2Authentication saml2Authentication = new Saml2Authentication((AuthenticatedPrincipal) auth.getPrincipal(), auth.getSaml2Response(), grantedAuthorities);
/*
//The details are replaced by the authentication.getDetails().
MyUserDetails userDetails = new MyUserDetails(authenticate.getName(),auth.getPrincipal());
saml2Authentication.setDetails(userDetails);
*/
return saml2Authentication;
});
Authentication authenticate = provider.authenticate(authentication);
//Doesn't sound like a good idea
if ((authenticate.getPrincipal() instanceof DefaultSaml2AuthenticatedPrincipal)) {
DefaultSaml2AuthenticatedPrincipal samlPrincipal = (DefaultSaml2AuthenticatedPrincipal) authenticate.getPrincipal();
MyUserDetails userDetails = new MyUserDetails(authenticate.getName(),
samlPrincipal.getFirstAttribute("SMFIRSTNAME")
, samlPrincipal.getFirstAttribute("SMLASTNAME")
, samlPrincipal.getFirstAttribute("SMEMAIL"));
((Saml2Authentication)authenticate).setDetails(defaultDISUserDetails);
}
return authenticate;
有更好的选择吗?
非常感谢您的帮助
此致