我有一个应用程序可以通过多个子域访问,因为品牌和支持信息是动态显示的。我们正在转向一个SSO解决方案,现在让它变得有趣。目前我将Spring Security SAML(1.0.1)添加到Spring Security组合中,并在IdP上使用WSO2 Identity Server。它运行得很好。
当存在多个同一地址的DNS条目时,问题在于保留服务提供商端的子域。例如,假设我将以下子域发送到完全相同的地方,即guy1.mistersite.com和guy2.mistersite.com。当首次通过guy1.mistersite.com启动应用服务器时首次访问应用程序时,来自SP的AuthnRequest将在AssertionConsumerServiceURL和Issuer中指示它来自guy1.mistersite.com。好。现在,从guy2.mistersite.com尝试下一次访问,AssertionConsumerServiceURL和Issuer实际上仍然在AuthnRequest中有guy1.mistersite.com。长号。
查看代码,您可以看到它已被有效缓存 org.springframework.security.saml.metadata.MetadataGeneratorFilter。当命中processMetadataInitialization()方法时,将检查是否已设置了hostedSPName,entityAlias和defaultBaseURL。如果他们是,那么,继续前进。这是有道理的。
是继承MetadataGeneratorFilter并重写processMetadataInitialization()真的是一个有效且“安全”的解决方案吗?
我已经做了一个概念验证,并注释掉了所有的空值检查,因此每次使用此方法时都会重新建立每个值,因此在一个简单的情况下,这样可以正常工作。我想知道,因为这个bean本质上是一个单例,当一个不同的子域请求同时出现时会发生什么。有没有机会被搞砸了?该方法中的同步块是否足以防止这种考虑?
所以,是的,如果这是一种安全且理智的方式来解决这个问题,就好像我是在正确的轨道上,请告诉我!还有别的想法。我是对的,我不是什么? :)
我们正在考虑改变基础架构和子域的方法模型,所以我想继续讨论使用新类扩展Spring Security SAML的可行性。
提前感谢! ;)
以下是我对该方法的快速修复(基本上只评论了一些内容):
protected void processMetadataInitialization(HttpServletRequest request) throws ServletException {
// In case the hosted SP metadata weren't initialized, let's do it now
//Forcing this to reload the host SP name every time to deal with various subdomains where a user could come to for the same app (think branding for partner companies)
// if (manager.getHostedSPName() == null) {
synchronized (MetadataManager.class) {
// if (manager.getHostedSPName() == null) {
try {
log.info("No default metadata configured, generating with default values, please pre-configure metadata for production use");
// Defaults
String alias = generator.getEntityAlias();
String baseURL = getDefaultBaseURL(request);
// Use default baseURL if not set
// if (generator.getEntityBaseURL() == null) {
log.warn("Generated default entity base URL {} based on values in the first server request. Please set property entityBaseURL on MetadataGenerator bean to fixate the value.", baseURL);
generator.setEntityBaseURL(baseURL);
// } else {
baseURL = generator.getEntityBaseURL();
// }
// Use default entityID if not set
// if (generator.getEntityId() == null) {
generator.setEntityId(getDefaultEntityID(baseURL, alias));
// }
EntityDescriptor descriptor = generator.generateMetadata();
ExtendedMetadata extendedMetadata = generator.generateExtendedMetadata();
log.info("Created default metadata for system with entityID: " + descriptor.getEntityID());
MetadataMemoryProvider memoryProvider = new MetadataMemoryProvider(descriptor);
memoryProvider.initialize();
MetadataProvider metadataProvider = new ExtendedMetadataDelegate(memoryProvider, extendedMetadata);
manager.addMetadataProvider(metadataProvider);
manager.setHostedSPName(descriptor.getEntityID());
manager.refreshMetadata();
} catch (MetadataProviderException e) {
log.error("Error generating system metadata", e);
throw new ServletException("Error generating system metadata", e);
}
// }
}
// }
}
安全配置的一部分:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="idpDiscoveryEnabled" value="false"/>
<property name="signMetadata" value="false"/>
</bean>
</property>
<!-- We leave these out and values are defaulted to entityId = url that user came in on
and entityId = <entityBaseUrl>/saml/metadata. We have to configure a SP in WSO2 for every
subdomain we have -->
<property name="wantAssertionSigned" value="false" />
</bean>
</constructor-arg>
</bean>
答案 0 :(得分:0)
我一直在谷歌搜索它,它已经看到两种可能的方法。根据规范,您可以将身份验证请求签名为SP,以便指定AssertionConsumerServiceURL,而不要求它作为SP元数据交换的一部分先前已发布和配置,但我不完全了解如何使用Spring执行此操作安全SAML扩展。以下是该信息的source。
我自己辩论的另一个问题是覆盖MetadataGenerator中的buildSPSSODescriptor,然后查找该环境的可能子域(我们在数据库中有可用的子域),然后我将遍历该列表并创建一个条目每一个人。
就像你这样做的方式,这最后一种方式似乎也是一种黑客攻击。希望这会有所帮助。
你最终做了什么?