Spring Security和嵌套的FilterChainProxy编写SAML服务提供程序
我试图找出涉及Spring Security和SAML的问题。 我们试图使用Spring Security(spring-security-core-3.1.1.RELEASE.jar)和SAML(spring-security-saml2-core-1.0.0-RC1-SNAPSHOT.jar)来修改我们的产品以成为SAML SP。 编辑:这是我的安全相关上下文xml(我认为!)的相关部分。 正如你所看到的,它与这个示例XML几乎相同。
<!-- Entry point to initialize authentication, default values taken from properties file -->
<bean id="samlEntryPoint" class="com.myproduct.samlsp.impl.PSSAMLEntryPoint">
<property name="defaultProfileOptions">
<bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
<property name="includeScoping" value="false"/>
</bean>
</property>
</bean>
<!-- Unsecured pages -->
<security:http security="none" pattern="/saml/web/**"/>
<security:http security="none" pattern="/logout.jsp"/>
<security:http security="none" pattern="/favicon.ico"/>
<security:http security="none" pattern="/images/**"/>
<security:http security="none" pattern="/scripts/**"/>
<security:http security="none" pattern="/flash/**"/>
<security:http security="none" pattern="/loggedout.html"/>
<!-- Secured pages -->
<security:http entry-point-ref="samlEntryPoint">
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</security:http>
<!-- IDP Discovery Service -->
<bean id="samlIDPDiscovery" class="org.springframework.security.saml.SAMLDiscovery">
<property name="idpSelectionPath" value="/WEB-INF/security/idpSelection.jsp"/>
</bean>
<bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map request-matcher="ant">
<security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
<security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
<security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/>
<security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
<security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
<security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
<security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/>
</security:filter-chain-map>
</bean>
症状是,在用IDP进行身份验证后,我的SP页面正确显示; 但是,更改URL(例如,单击任何链接)会立即将我发送回IDP。 我想我已经明白了为什么,但我不知道为什么并非总是如此。
我对Spring Security的理解是,授权检查全部基于SecurityContextHolder。 也就是说,在持有者身上放置一个认证对象,并且所有内容都会对它进行认证检查。 然后SecurityContextPersistenceFilter负责维护会话库以匹配。
所以,当我跟踪Spring Security代码时,我看到SecurityContextPersistenceFilter具有以下代码:
SecurityContext contextBeforeChainExecution = repo.loadContext(holder);
try {
SecurityContextHolder.setContext(contextBeforeChainExecution);
chain.doFilter(holder.getRequest(), holder.getResponse());
} finally {
SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
// Crucial removal of SecurityContextHolder contents - do this before anything else.
SecurityContextHolder.clearContext();
repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
....
}
到现在为止还挺好。 然后,我看看FilterChainProxy并找到:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
doFilterInternal(request, response, chain);
} finally {
// SEC-1950
SecurityContextHolder.clearContext(); <------- Key line here
}
}
这似乎还好。 由于FilterChainProxy只能在所有Spring Security过滤器的基础上调用一次,因此在此时清除SecurityContextHolder并不是问题。
但是,这不是发生了什么事。 实际发生的事情是FilterChainProxy中的clearContext被调用BEFORE SecurityContextPersistenceFilter有机会将它从context读入contextAfterChainExecution。 发生这种情况的原因是因为FilterChainProxy实际上在调用链中出现两次。 我知道这是因为我在FilterChainProxy.doFilter中设置了一个断点,并且它被调用了两次。 它第一次被调用时,它的FilterChain中有另一个FilterChainProxy实例。 以下是FilterChainProxy的getFilters方法返回的过滤器堆栈:
org.springframework.security.saml.metadata.MetadataGeneratorFilter@78104d3c
org.springframework.security.web.context.SecurityContextPersistenceFilter@168c795e
FilterChainProxy[ Filter Chains: [ .... my patterns ] ],
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7fffde92
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@e2d09d7
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1c2b968f
org.springframework.security.web.session.SessionManagementFilter@395f222a
org.springframework.security.web.access.ExceptionTranslationFilter@372e6f09
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@7dab91aa
有了这个过滤器链,我不明白SecurityContextPersistenceFilter是如何工作的:看起来SecurityContextHolder在它有机会坚持它之前总是被清除。
这里有什么明显的错误吗? 我是否误解了Spring Security中的某些内容(很有可能!)
我无法得到任何明确的陈述,但问题似乎与Spring Security 3.1.1在弹性SAML或实际上使用相同种类的嵌套FilterChainProxys的实现中表现不佳。 它出现FilterChainProxy完全重写为3.1.1。 当我查看最新版本(3.1.4)时,我注意到在finally子句中有一个检查,只有清除了SecurityContextHolder(“SEC-1950”),如果它是第一次调用过滤器。
因此,将spring security升级到3.1.4解决了这个问题。
链接地址: http://www.djcxy.com/p/71857.html上一篇: Spring Security and nested FilterChainProxy writing SAML Service Provider
下一篇: Replace everytime this color by that color in css with jquery