我正在尝试将Spring Security SAML Extension与Spring Boot集成.
关于这件事,我确实开发了一个完整的示例应用程序.它的源代码可以在GitHub上找到:
通过将其作为Spring Boot应用程序运行(针对SDK内置的Application Server运行),WebApp可以正常工作.
不幸的是,相同的AuthN进程在Undertow/WildFly上根本不起作用.
根据日志,IdP实际上执行AuthN过程:我的自定义UserDetails
实现的指令被正确执行.尽管有执行流程,但Spring并未设置并保留当前用户的权限.
@Component
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {
// Logger
private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);
@Override
public Object loadUserBySAML(SAMLCredential credential)
throws UsernameNotFoundException, SSOUserAccountNotExistsException {
String userID = credential.getNameID().getValue();
if (userID.compareTo("jdoe@samplemail.com") != 0) { // We're simulating the data access.
LOG.warn("SSO User Account not found into the system");
throw new SSOUserAccountNotExistsException("SSO User Account not found into …
Run Code Online (Sandbox Code Playgroud) 我想在我的基于Spring的应用程序中实现单点登录(SSO)身份验证层,目的是支持来自不同安全域的身份验证和授权.我选择Shibboleth作为IdP,但我还没有确定我将用于SP的内容.
选择是:
Spring Security SAML Extension:组件使新的和现有的应用程序能够在基于SAML 2.0协议的联合中充当服务提供者,并启用Web单点登录.Spring Security Extension允许在单个应用程序中无缝组合SAML 2.0和其他身份验证和联合机制.所有在身份提供商模式下支持SAML 2.0的产品(例如ADFS 2.0,Shibboleth,OpenAM/OpenSSO,RM5 IdM或Ping Federate)都可用于连接Spring Security SAML Extension.
Shibboleth(也称为SP):Shibboleth是一种基于Web的技术,可实现SAML的HTTP/POST,工件和属性推送配置文件,包括身份提供程序(IdP)和服务提供程序(SP)组件.
所以,我有一些问题:
最好的问候,V.
spring-security shibboleth single-sign-on saml-2.0 spring-saml
我正在尝试使用Spring Security SAML扩展将SAML SSO与Spring Security集成.之前,我成功地运行了一个概念验证:https://github.com/vdenotaris/spring-boot-security-saml-sample.不幸的是,在将配置移动到我的项目后,它无法正常工作.
在分析了日志之后,我发现我的应用程序(SP)正在从提供的URL正确下载IdP元数据.但是,在尝试通过在浏览器中尝试https:// localhost:8443/saml/metadata下载我的SP的元数据后,将引发以下异常:
javax.servlet.ServletException: Error initializing metadata
at org.springframework.security.saml.metadata.MetadataDisplayFilter.processMetadataDisplay(MetadataDisplayFilter.java:120)
at org.springframework.security.saml.metadata.MetadataDisplayFilter.doFilter(MetadataDisplayFilter.java:88)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1645)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:564)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:498)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1045)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:98)
at org.eclipse.jetty.server.Server.handle(Server.java:461)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:284)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:244)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:534)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.opensaml.saml2.metadata.provider.MetadataProviderException: No hosted service provider is configured and no …
Run Code Online (Sandbox Code Playgroud) 我通过复制我计划连接的IDP的509条目生成了testIdp.cer文件.然后我通过执行以下命令创建了JKS文件
keytool -importcert -alias adfssigning -keystore C:\Users\user\Desktop\samlKeystore.jks -file C:\Users\user\Desktop\testIdp.cer
Run Code Online (Sandbox Code Playgroud)
执行时,它要求输入我已给出密码的密码.对于"信任这个证书?[no]:"这个问题,我给出了"y"作为输入.消息出现为"证书已添加到密钥库".
然后我在securityContext.xml中配置了以下详细信息
<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/samlKeystore.jks"/>
<constructor-arg type="java.lang.String" value="mypassword"/>
<constructor-arg>
<map>
<entry key="adfssigning" value="mypassword"/>
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="adfssigning"/>
</bean>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="alias" value="adfssigning" />
<property name="signingKey" value="adfssigning"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
但是当我运行应用程序时,我在服务器启动时以及加载应用程序的主页时会遇到以下两个异常.如果我错过任何其他内容,任何人都可以告诉我.
启动服务器时发生此异常
Caused by: org.opensaml.saml2.metadata.provider.FilterException: Signature trust establishment failed for metadata entry
at org.opensaml.saml2.metadata.provider.SignatureValidationFilter.verifySignature(SignatureValidationFilter.java:327)
at org.opensaml.saml2.metadata.provider.SignatureValidationFilter.processEntityGroup(SignatureValidationFilter.java:240)
at org.opensaml.saml2.metadata.provider.SignatureValidationFilter.doFilter(SignatureValidationFilter.java:158)
at org.opensaml.saml2.metadata.provider.AbstractMetadataProvider.filterMetadata(AbstractMetadataProvider.java:493)
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.processNonExpiredMetadata(AbstractReloadingMetadataProvider.java:395)
Run Code Online (Sandbox Code Playgroud)
当我运行应用程序的主页时,会发生此异常
java.lang.UnsupportedOperationException: trusted certificate entries are not password-protected
at java.security.KeyStoreSpi.engineGetEntry(Unknown Source)
at java.security.KeyStore.getEntry(Unknown Source)
at org.opensaml.xml.security.credential.KeyStoreCredentialResolver.resolveFromSource(KeyStoreCredentialResolver.java:132)
Run Code Online (Sandbox Code Playgroud) 在我们目前的情况下,我们的基于Web的应用程序(SP)已经使用Spring Security SAML扩展集成了SSO.我们的产品是SaaS,我们有不同的客户,他们可能在其末端配置了不同的IDP(身份提供商).现在我们正在努力为我们的移动应用程序提供SSO支持.
经过一番搜索,我遇到了3个可以实现的解决方案:
1)使用Web视图:当为客户端启用SAML时,移动应用程序将嵌入Web视图,该视图在打开移动应用程序时呈现IDP登录页面.将触发SP侧的URL,这将触发SAML重定向回IDP.因此,webview将执行SP发起的登录流程.但是,由于webview不使用cookie空间,因此每次应用程序被终止或会话过期时,用户都必须登录该应用程序.另外由于webview不是浏览器,我已经读过它在HTTP重定向期间可能无法处理边缘情况.
2)使用Native SSO App:IDP通常提供本机SSO应用程序,移动应用程序可以登录IDP.移动应用程序可以通过相应IDP提供的SDK与IDP的本机应用程序进行交互.但由于我们的移动应用程序应该能够支持许多IDP的SSO,如果我们遵循这种方法,我们可能必须为每个IDP集成多个Native SSO应用程序.我不确定这在我们的场景中是否合理
3)使用OAuth和SAML:第三个选项是为我们的移动应用添加OAuth支持.Salesforce等IDP支持OAuth授权移动应用,但我不确定所有IDP是否支持OAuth,以及为移动应用实施OAuth和SAML有多困难.
谁能告诉我在上面的场景中哪种方法更可取,还是有更好的方法我没有考虑过?有什么建议?
非常感谢!
为了从远程源获取元数据,我ExtendedMetadataDelegate
按如下方式定义了一个bean:
@Bean
@Qualifier("replyMeta")
public ExtendedMetadataDelegate replyMetadataProvider() throws MetadataProviderException {
String metadataURL = "https://ststest.mydomain.it/FederationMetadata/2007-06/FederationMetadata.xml";
final Timer backgroundTaskTimer = new Timer(true);
HTTPMetadataProvider provider = new HTTPMetadataProvider(
backgroundTaskTimer, httpClient(), metadataURL);
provider.setParserPool(parserPool());
ExtendedMetadataDelegate emd = new ExtendedMetadataDelegate(
provider, new ExtendedMetadata());
return emd;
}
Run Code Online (Sandbox Code Playgroud)
为了确保签名信任的建立,我在JDK密钥库和应用程序密钥库中都添加了相关密钥(第二步可能还不够); 尽管如此,运行webapp会出错.
[2014-08-18 14:36:47.200] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Attempting to validate signature using key from supplied credential
[2014-08-18 14:36:47.200] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Creating XMLSignature object
[2014-08-18 14:36:47.206] boot - 6000 DEBUG [localhost-startStop-1] …
Run Code Online (Sandbox Code Playgroud) 我们使用ADFS作为IDP,我们的应用程序充当SP.以下是Auth响应示例
<?xml version="1.0" encoding="UTF-8"?>
<Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_82062d3d-897f-473e-90ad-0bb351d63b22" IssueInstant="2015-04-29T20:39:17.240Z" Version="2.0">
<Issuer>http://adfs/services/trust</Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#_82062d3d-897f-473e-90ad-0bb351d63b22">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue />
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>certificate..... </ds:X509Certificate>
</ds:X509Data>
</KeyInfo>
</ds:Signature>
<Subject>
<NameID>username</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="923ki0eg8h7g7y2243fi9jbdd1977j9" NotOnOrAfter="2015-04-29T20:44:17.240Z" Recipient="https://localhost/saml/SSO" />
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2015-04-29T20:39:17.240Z" NotOnOrAfter="2015-04-29T21:39:17.240Z">
<AudienceRestriction>
<Audience>https://localhost/saml/metadata</Audience>
</AudienceRestriction>
</Conditions>
<AuthnStatement AuthnInstant="2015-04-29T20:39:17.162Z" SessionIndex="_92062g3d-897f-473e-90ad-0aa351d63b22">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
Run Code Online (Sandbox Code Playgroud)
我面临的问题可分为两种情况:
闲置1小时后,我在本地注销用户.服务器会话到期是默认值30分钟.如果用户正在积极处理某些事情,我有我的代码每隔10分钟发送一次心跳ping.现在,问题是当用户在会话到期1小时后尝试登录时,我得到以下异常
Caused by: org.springframework.security.authentication.CredentialsExpiredException: Authentication statement is …
Run Code Online (Sandbox Code Playgroud)我试图SwitchUserFilter
在Spring中实现模拟,但是我遇到了错误.没有这个实现,项目运行良好.此外,该项目使用Java配置而非xml配置,并具有SecureAuth身份验证.并且代码中涉及到SecurityConfig类的部分是:
@Configuration
@ComponentScan(basePackages = {"com.project.*"})
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
@PropertySource("classpath:app.properties")
@Import({TransactionManagersConfig.class, MailConfig.class})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SwitchUserFilter switchUserFilter;
@Autowired
protected AuthenticationSuccessHandler authenticationSuccessHandler;
@Bean
public UserDetailsService userDetailsServiceBean() {
try {
return super.userDetailsServiceBean();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean
public SwitchUserFilter switchUserFilter() {
SwitchUserFilter switchUserFilter = new SwitchUserFilter();
switchUserFilter.setUserDetailsService(userDetailsServiceBean());
switchUserFilter.setUsernameParameter("username");
switchUserFilter.setSwitchUserUrl("/switch");
switchUserFilter.setExitUserUrl("/exit");
switchUserFilter.setTargetUrl("/");
return switchUserFilter;
}
//more beans
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().disable();
http //SAML CONFIG …
Run Code Online (Sandbox Code Playgroud) 我正在尝试基于"spring-security-saml2-sample"设置SP,但是当我在Tomcat上部署WAR文件时,我得到以下异常:
Initialization of metadata provider org.opensaml.saml2.metadata.provider.HTTPMetadataProvider@443c35d3 failed, provider will be ignored
org.opensaml.saml2.metadata.provider.MetadataProviderException: org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from
https://dominio.com/fed/idp/metadata
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:266)
at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.doInitialization(AbstractReloadingMetadataProvider.java:236)
at org.opensaml.saml2.metadata.provider.AbstractMetadataProvider.initialize(AbstractMetadataProvider.java:407)
at org.springframework.security.saml.metadata.ExtendedMetadataDelegate.initialize(ExtendedMetadataDelegate.java:167)
at org.springframework.security.saml.metadata.MetadataManager.initializeProvider(MetadataManager.java:397)
at org.springframework.security.saml.metadata.MetadataManager.refreshMetadata(MetadataManager.java:245)
at org.springframework.security.saml.metadata.CachingMetadataManager.refreshMetadata(CachingMetadataManager.java:86)
at org.springframework.security.saml.metadata.MetadataManager.afterPropertiesSet(MetadataManager.java:141)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:876)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:818)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) …
Run Code Online (Sandbox Code Playgroud) 我在获取Spring SAML集成时遇到问题,为我的IdP生成正确的元数据文件.我获得了新的SHA256 SSL证书.我已经完成了创建相应keyStore的所有步骤,并将我的Spring安全配置文件全部设置完毕.我确实有98%的方式,但生成的元数据文件中缺少一件事,我不能为我的生活弄清楚为什么它没有设置.
这是MetadataGeneratorFilter的ExtendedMetadata配置:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:myentityidhere"/>
<property name="entityBaseURL" value="https://${saml.url}"/>
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="signMetadata" value="true"/>
<property name="signingAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<property name="alias" value="ceo"/>
<property name="signingKey" value="${saml.sp.alias}"/>
<property name="encryptionKey" value="${saml.sp.alias}"/>
</bean>
</property>
</bean>
</constructor-arg>
Run Code Online (Sandbox Code Playgroud)
当我运行我的应用程序并转到/ saml/metadata URI以获取Spring生成我需要发送到我的IdP的元数据文件时,SHA256算法在SignatureMethod上正确设置,但子DigestMethod标记的算法值仍然设置到SHA1,当我需要将ALSO设置为SHA256以及DigestValue作为SHA256值而不是SHA1值.
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#urn_myentityidhere">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>xxxxxxx</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
Run Code Online (Sandbox Code Playgroud)
有人可以指导我如何/我需要设置什么来将DigestMethod算法值设置为256?我想,因为它是SignedInfo标记的子代,它将从Extendedmetadata配置继承signedAlgorithm值,但实际上并非如此.
任何帮助将不胜感激.非常感谢.
解决方案 - 万一有人关心
因此,经过一天的挖掘,我决定自己实施.我通过添加字段digestMethodAlgorithm扩展了ExtendedMetadata类,并添加了适当的getter/setter:
/**
* Algorithm used for creation of digest method of this entity. At the …
Run Code Online (Sandbox Code Playgroud)