springboot集成saml2.0
时间: 2023-09-18 16:10:14 浏览: 320
springboot2.0
SAML(Security Assertion Markup Language)是一种基于 XML 的标准,用于在不同的身份验证和授权系统之间交换身份验证和授权数据。在集成 SAML 2.0 单点登录(SSO)到 Spring Boot 应用程序时,通常需要使用 Spring Security SAML 扩展。
以下是在 Spring Boot 中集成 SAML 2.0 的基本步骤:
1. 添加 Spring Security SAML 依赖:
```xml
<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.10.RELEASE</version>
</dependency>
```
2. 配置 Spring Security SAML:
在 Spring Boot 应用程序中,可以通过在 application.properties 或 application.yml 文件中添加以下配置来配置 Spring Security SAML:
```yaml
# SAML配置
security.saml2.metadata-url=http://localhost:8080/saml/metadata
security.saml2.entity-id=http://localhost:8080/saml/metadata
security.saml2.keystore-location=classpath:samlKeystore.jks
security.saml2.keystore-password=secret
security.saml2.private-key-password=secret
security.saml2.protocol=urn:oasis:names:tc:SAML:2.0:protocol
security.saml2.tls=true
```
这些配置包括元数据 URL、实体 ID、密钥库位置、密钥库密码、私钥密码、协议和 TLS 是否启用。
3. 配置 Spring Security:
在 Spring Boot 应用程序中,可以使用以下示例代码配置 Spring Security:
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SAMLUserDetailsService samlUserDetailsService;
@Autowired
private SAMLAuthenticationProvider samlAuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.and()
.httpBasic();
}
@Bean
public SAMLConfigurer saml() {
return new SAMLConfigurer();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(samlAuthenticationProvider);
}
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
SAMLAuthenticationProvider provider = new SAMLAuthenticationProvider();
provider.setUserDetails(samlUserDetailsService);
provider.setForcePrincipalAsString(false);
return provider;
}
@Bean
public SAMLBootstrap samlBootstrap() {
return new SAMLBootstrap();
}
@Bean
public SAMLUserDetailsService samlUserDetailsService() {
return new SAMLUserDetailsServiceImpl();
}
}
```
这里我们配置了一个基本的 Spring Security 配置,其中包括允许所有 /saml/** 请求,使用 SAML 配置和启用 HTTP Basic 认证。我们还将 SAMLUserDetailsService 和 SAMLAuthenticationProvider 添加到了配置中。
4. 配置 SAML 元数据:
最后,我们需要为 SAML 配置创建元数据文件。可以使用以下示例代码创建元数据文件:
```java
@Configuration
public class SAMLConfig {
@Autowired
private SAMLUserDetailsService samlUserDetailsService;
@Autowired
private SAMLAuthenticationProvider samlAuthenticationProvider;
@Value("${security.saml2.metadata-url}")
private String metadataUrl;
@Value("${security.saml2.entity-id}")
private String entityId;
@Value("${security.saml2.keystore-location}")
private String keystoreLocation;
@Value("${security.saml2.keystore-password}")
private String keystorePassword;
@Value("${security.saml2.private-key-password}")
private String privateKeyPassword;
@Bean
public SAMLConfigurer saml() {
return new SAMLConfigurer();
}
@Bean
public SAMLContextProviderImpl contextProvider() {
return new SAMLContextProviderImpl();
}
@Bean
public SAMLDefaultLogger samlLogger() {
return new SAMLDefaultLogger();
}
@Bean
public SAMLDefaultLogoutHandler logoutHandler() {
return new SAMLDefaultLogoutHandler();
}
@Bean
public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
return new SAMLLogoutProcessingFilter(logoutHandler(), new SecurityContextLogoutHandler());
}
@Bean
public SAMLLogoutFilter samlLogoutFilter() {
return new SAMLLogoutFilter(logoutHandler(), new LogoutHandler[] { logoutHandler() },
new LogoutHandler[] { logoutHandler() });
}
@Bean
public SAMLProcessorImpl processor() {
return new SAMLProcessorImpl(Collections.singletonList(new HTTPPostBinding())));
}
@Bean
public VelocityEngine velocityEngine() {
return VelocityFactory.getEngine();
}
@Bean(initMethod = "initialize")
public StaticBasicParserPool parserPool() {
return new StaticBasicParserPool();
}
@Bean(name = "samlWebSSOHoKProcessingFilter")
public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
SAMLWebSSOHoKProcessingFilter filter = new SAMLWebSSOHoKProcessingFilter();
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "samlAuthenticationFilter")
public SAMLAuthenticationFilter samlAuthenticationFilter() throws Exception {
SAMLAuthenticationFilter filter = new SAMLAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "successRedirectHandler")
public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successRedirectHandler.setDefaultTargetUrl("/");
return successRedirectHandler;
}
@Bean(name = "authenticationFailureHandler")
public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
failureHandler.setUseForward(true);
failureHandler.setDefaultFailureURL("/error");
return failureHandler;
}
@Bean(name = "metadata")
public CachingMetadataManager metadata() throws MetadataProviderException {
List<MetadataProvider> providers = new ArrayList<>();
providers.add(new HTTPMetadataProvider(metadataUrl, 5000));
providers.add(new ResourceBackedMetadataProvider(new Timer(), new ClasspathResource("metadata/idp.xml")));
CachingMetadataManager manager = new CachingMetadataManager(providers);
manager.setRefreshCheckInterval(3600);
return manager;
}
@Bean(name = "webSSOprofileConsumer")
public WebSSOProfileConsumer webSSOprofileConsumer() {
return new WebSSOProfileConsumerImpl();
}
@Bean(name = "webSSOprofile")
public WebSSOProfile webSSOprofile() {
return new WebSSOProfileImpl();
}
@Bean(name = "hokWebSSOProfileConsumer")
public WebSSOProfileConsumerHoKImpl hokWebSSOProfileConsumer() {
return new WebSSOProfileConsumerHoKImpl();
}
@Bean(name = "hokWebSSOProfile")
public WebSSOProfileHoKImpl hokWebSSOProfile() {
return new WebSSOProfileHoKImpl();
}
@Bean(name = "defaultWebSSOProfileConsumer")
public WebSSOProfileConsumer defaultWebSSOProfileConsumer() {
return new WebSSOProfileConsumerImpl();
}
@Bean(name = "defaultWebSSOProfile")
public WebSSOProfile defaultWebSSOProfile() {
return new WebSSOProfileImpl();
}
@Bean(name = "metadataDisplayFilter")
public MetadataDisplayFilter metadataDisplayFilter() {
return new MetadataDisplayFilter();
}
@Bean(name = "ssoFilter")
public SAMLProcessingFilter ssoFilter() throws Exception {
SAMLProcessingFilter filter = new SAMLProcessingFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "samlEntryPoint")
public SAMLEntryPoint samlEntryPoint() {
SAMLEntryPoint entryPoint = new SAMLEntryPoint();
entryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
return entryPoint;
}
@Bean(name = "defaultWebSSOProfileOptions")
public WebSSOProfileOptions defaultWebSSOProfileOptions() {
WebSSOProfileOptions options = new WebSSOProfileOptions();
options.setIncludeScoping(false);
return options;
}
@Bean(name = "metadataGeneratorFilter")
public MetadataGeneratorFilter metadataGeneratorFilter() {
return new MetadataGeneratorFilter(metadataGenerator());
}
@Bean(name = "metadataGenerator")
public MetadataGenerator metadataGenerator() {
MetadataGenerator metadataGenerator = new MetadataGenerator();
metadataGenerator.setEntityId(entityId);
metadataGenerator.setExtendedMetadata(extendedMetadata());
metadataGenerator.setIncludeDiscoveryExtension(false);
metadataGenerator.setKeyManager(keyManager());
return metadataGenerator;
}
@Bean(name = "keyManager")
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource(keystoreLocation);
String storePass = keystorePassword;
Map<String, String> passwords = new HashMap<>();
passwords.put("apollo", privateKeyPassword);
return new JKSKeyManager(storeFile, storePass, passwords, "apollo");
}
@Bean(name = "extendedMetadata")
public ExtendedMetadata extendedMetadata() {
ExtendedMetadata extendedMetadata = new ExtendedMetadata();
extendedMetadata.setIdpDiscoveryEnabled(false);
extendedMetadata.setSignMetadata(true);
return extendedMetadata;
}
@Bean(name = "metadataDisplay")
public StaticViewResolver metadataDisplay() {
return new StaticViewResolver("/WEB-INF/views/metadata.jsp");
}
@Bean(name = "samlLogoutFilter")
public SAMLLogoutFilter samlLogoutFilter() {
return new SAMLLogoutFilter(successLogoutHandler(), new LogoutHandler[] { logoutHandler() },
new LogoutHandler[] { logoutHandler() });
}
@Bean(name = "successLogoutHandler")
public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
successLogoutHandler.setDefaultTargetUrl("/");
return successLogoutHandler;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(samlAuthenticationProvider);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER");
}
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
SAMLAuthenticationProvider provider = new SAMLAuthenticationProvider();
provider.setUserDetails(samlUserDetailsService);
provider.setForcePrincipalAsString(false);
return provider;
}
@Bean
public SAMLBootstrap samlBootstrap() {
return new SAMLBootstrap();
}
@Bean
public SAMLUserDetailsService samlUserDetailsService() {
return new SAMLUserDetailsServiceImpl();
}
@Bean(name = "metadata")
public CachingMetadataManager metadata() throws MetadataProviderException {
List<MetadataProvider> providers = new ArrayList<>();
providers.add(new HTTPMetadataProvider(metadataUrl, 5000));
providers.add(new ResourceBackedMetadataProvider(new Timer(), new ClasspathResource("metadata/idp.xml")));
CachingMetadataManager manager = new CachingMetadataManager(providers);
manager.setRefreshCheckInterval(3600);
return manager;
}
@Bean(name = "samlWebSSOHoKProcessingFilter")
public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
SAMLWebSSOHoKProcessingFilter filter = new SAMLWebSSOHoKProcessingFilter();
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "samlAuthenticationFilter")
public SAMLAuthenticationFilter samlAuthenticationFilter() throws Exception {
SAMLAuthenticationFilter filter = new SAMLAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "successRedirectHandler")
public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successRedirectHandler.setDefaultTargetUrl("/");
return successRedirectHandler;
}
@Bean(name = "authenticationFailureHandler")
public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
failureHandler.setUseForward(true);
failureHandler.setDefaultFailureURL("/error");
return failureHandler;
}
@Bean(name = "ssoFilter")
public SAMLProcessingFilter ssoFilter() throws Exception {
SAMLProcessingFilter filter = new SAMLProcessingFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successRedirectHandler());
filter.setAuthenticationFailureHandler(authenticationFailureHandler());
return filter;
}
@Bean(name = "samlEntryPoint")
public SAMLEntryPoint samlEntryPoint() {
SAMLEntryPoint entryPoint = new SAMLEntryPoint();
entryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
return entryPoint;
}
@Bean(name = "defaultWebSSOProfileOptions")
public WebSSOProfileOptions defaultWebSSOProfileOptions() {
WebSSOProfileOptions options = new WebSSOProfileOptions();
options.setIncludeScoping(false);
return options;
}
@Bean(name = "metadataGeneratorFilter")
public MetadataGeneratorFilter metadataGeneratorFilter() {
return new MetadataGeneratorFilter(metadataGenerator());
}
@Bean(name = "metadataGenerator")
public MetadataGenerator metadataGenerator() {
MetadataGenerator metadataGenerator = new MetadataGenerator();
metadataGenerator.setEntityId(entityId);
metadataGenerator.setExtendedMetadata(extendedMetadata());
metadataGenerator.setIncludeDiscoveryExtension(false);
metadataGenerator.setKeyManager(keyManager());
return metadataGenerator;
}
@Bean(name = "keyManager")
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource(keystoreLocation);
String storePass = keystorePassword;
Map<String, String> passwords = new HashMap<>();
passwords.put("apollo", privateKeyPassword);
return new JKSKeyManager(storeFile, storePass, passwords, "apollo");
}
@Bean(name = "extendedMetadata")
public ExtendedMetadata extendedMetadata() {
ExtendedMetadata extendedMetadata = new ExtendedMetadata();
extendedMetadata.setIdpDiscoveryEnabled(false);
extendedMetadata.setSignMetadata(true);
return extendedMetadata;
}
@Bean(name = "metadataDisplay")
public StaticViewResolver metadataDisplay() {
return new StaticViewResolver("/WEB-INF/views/metadata.jsp");
}
@Bean(name = "samlLogoutFilter")
public SAMLLogoutFilter samlLogoutFilter() {
return new SAMLLogoutFilter(successLogoutHandler(), new LogoutHandler[] { logoutHandler() },
new LogoutHandler[] { logoutHandler() });
}
@Bean(name = "successLogoutHandler")
public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
successLogoutHandler.setDefaultTargetUrl("/");
return successLogoutHandler;
}
}
```
该配置包括 SAML 元数据、SAML 上下文提供程序、SAML 日志记录器、SAML 注销处理程序、SAML 注销过滤器、SAML 处理器、SAML 速度引擎、SAML 解析器池、SAML WebSSO 处理过滤器、SAML 认证过滤器、SAML 成功重定向处理程序、SAML 认证失败处理程序、元数据管理器、WebSSOProfileConsumer、WebSSOProfile、WebSSOProfileConsumerHoKImpl、WebSSOProfileHoKImpl、MetadataDisplayFilter、SAMLProcessingFilter、SAMLEntryPoint、WebSSOProfileOptions、MetadataGeneratorFilter、MetadataGenerator、KeyManager、ExtendedMetadata、StaticViewResolver 和 SimpleUrlLogoutSuccessHandler。
这个配置可能看起来很复杂,但它是一个完整的 SAML 配置,包括 SAML 元数据的生成和管理、SAML 交互过滤器的配置、SAML 认证过滤器的配置、SAML 注销过滤器的配置、SAML 上下文提供程序的配置以及其他一些关键组件的配置。
这就是在 Spring Boot 中集成 SAML 2.0 的基本步骤。当然,具体的实现细节可能因实际情况而异,但这应该足以帮助您开始使用 SAML 2.0 单点登录(SSO)集成。
阅读全文