Spring 安全 SAML 和 UserDetailsService
Spring Security SAML and UserDetailsService
我正在使用 Spring Security 5.6 中内置的实现将 SAML 集成到 Spring 启动应用程序中。许多联机帮助都引用了现已弃用的外部库实现 (https://github.com/spring-projects/spring-security-saml),因此我正在关注此文档:
https://docs.spring.io/spring-security/reference/servlet/saml2/login/index.html
我有这个交互工作,我现在正在从 SAML 进行身份验证。这是配置:
spring:
security:
saml2:
relyingparty:
registration:
adfs:
signing:
credentials:
- private-key-location: "file:///C:/tmp/keys/private.key"
certificate-location: "file:///C:/tmp/keys/public.crt"
identityprovider:
entity-id: << SNIPPED >>
verification.credentials:
- certificate-location: "classpath:saml-certificate/adfs.crt"
singlesignon:
url: << SNIPPED >>
sign-request: true
代码现在看起来像这样:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;
@Autowired
public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository {
_relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
http
.authorizeRequests()
.antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.and().csrf().ignoringAntMatchers("/servers/**/searches")
.and()
.saml2Login(withDefaults())
.saml2Logout(withDefaults())
.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
}
}
问题是我需要重新映射用户详细信息以设置正确的角色,并将登录限制为具有正确 Linux 权限的用户。正在更正断言中返回的权限;我只需要验证它们是否正确或登录失败。
Spring 安全文档中有一节是关于与 UserDetailsService 协调的,这似乎正是我所需要的。
然而,当我像示例一样实现它时,我现在从 Spring 得到以下错误:
No assertions found in response.
这是更新后的代码:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;
private final AuthenticationService _userDetailsService;
@Autowired
public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, AuthenticationService userDetailsService) {
_relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
_userDetailsService = userDetailsService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
authenticationProvider.setResponseAuthenticationConverter(responseToken -> {
Saml2Authentication authentication = OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter().convert(responseToken);
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
String username = assertion.getSubject().getNameID().getValue();
UserDetails userDetails = _userDetailsService.loadUserByUsername(username);
authentication.setDetails(userDetails);
return authentication;
});
// add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
http
.authorizeRequests()
.antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.and().csrf().ignoringAntMatchers("/servers/**/searches")
.and()
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))
.saml2Logout(withDefaults())
.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
}
}
所以基本上这从 SAML 得到了正确的响应:
.saml2Login(withDefaults())
当我切换到这个时,SAML 响应缺少断言:
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))
我一直在寻找其他解决方案,但正如我所说,很少有示例不使用旧的已弃用的 SAML 库 Spring。
有什么想法吗?
检查 Spring Boot 是否正在导入版本 3 和版本 4 打开 SAML。如果仅使用版本 4.
Spring 安全示例有一个 SAML2 示例。项目中的build.gradle包含以下内容:
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
}
dependencies {
constraints {
implementation "org.opensaml:opensaml-core:4.1.1"
implementation "org.opensaml:opensaml-saml-api:4.1.1"
implementation "org.opensaml:opensaml-saml-impl:4.1.1"
}
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.security:spring-security-saml2-service-provider'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
testImplementation 'net.sourceforge.htmlunit:htmlunit:2.44.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.awaitility:awaitility:4.2.0'
}
参考文献:
我正在使用 Spring Security 5.6 中内置的实现将 SAML 集成到 Spring 启动应用程序中。许多联机帮助都引用了现已弃用的外部库实现 (https://github.com/spring-projects/spring-security-saml),因此我正在关注此文档:
https://docs.spring.io/spring-security/reference/servlet/saml2/login/index.html
我有这个交互工作,我现在正在从 SAML 进行身份验证。这是配置:
spring:
security:
saml2:
relyingparty:
registration:
adfs:
signing:
credentials:
- private-key-location: "file:///C:/tmp/keys/private.key"
certificate-location: "file:///C:/tmp/keys/public.crt"
identityprovider:
entity-id: << SNIPPED >>
verification.credentials:
- certificate-location: "classpath:saml-certificate/adfs.crt"
singlesignon:
url: << SNIPPED >>
sign-request: true
代码现在看起来像这样:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;
@Autowired
public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository {
_relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
http
.authorizeRequests()
.antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.and().csrf().ignoringAntMatchers("/servers/**/searches")
.and()
.saml2Login(withDefaults())
.saml2Logout(withDefaults())
.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
}
}
问题是我需要重新映射用户详细信息以设置正确的角色,并将登录限制为具有正确 Linux 权限的用户。正在更正断言中返回的权限;我只需要验证它们是否正确或登录失败。
Spring 安全文档中有一节是关于与 UserDetailsService 协调的,这似乎正是我所需要的。
然而,当我像示例一样实现它时,我现在从 Spring 得到以下错误:
No assertions found in response.
这是更新后的代码:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;
private final AuthenticationService _userDetailsService;
@Autowired
public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, AuthenticationService userDetailsService) {
_relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
_userDetailsService = userDetailsService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
authenticationProvider.setResponseAuthenticationConverter(responseToken -> {
Saml2Authentication authentication = OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter().convert(responseToken);
Assertion assertion = responseToken.getResponse().getAssertions().get(0);
String username = assertion.getSubject().getNameID().getValue();
UserDetails userDetails = _userDetailsService.loadUserByUsername(username);
authentication.setDetails(userDetails);
return authentication;
});
// add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());
http
.authorizeRequests()
.antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.and().csrf().ignoringAntMatchers("/servers/**/searches")
.and()
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))
.saml2Logout(withDefaults())
.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
}
}
所以基本上这从 SAML 得到了正确的响应:
.saml2Login(withDefaults())
当我切换到这个时,SAML 响应缺少断言:
.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))
我一直在寻找其他解决方案,但正如我所说,很少有示例不使用旧的已弃用的 SAML 库 Spring。
有什么想法吗?
检查 Spring Boot 是否正在导入版本 3 和版本 4 打开 SAML。如果仅使用版本 4.
Spring 安全示例有一个 SAML2 示例。项目中的build.gradle包含以下内容:
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
}
dependencies {
constraints {
implementation "org.opensaml:opensaml-core:4.1.1"
implementation "org.opensaml:opensaml-saml-api:4.1.1"
implementation "org.opensaml:opensaml-saml-impl:4.1.1"
}
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.security:spring-security-saml2-service-provider'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
testImplementation 'net.sourceforge.htmlunit:htmlunit:2.44.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.awaitility:awaitility:4.2.0'
}
参考文献: