OpenSAML / Spring 安全设置,因此在 Tomcat 上重新部署有效

Posted

技术标签:

【中文标题】OpenSAML / Spring 安全设置,因此在 Tomcat 上重新部署有效【英文标题】:OpenSAML / Spring security setup so redeploy on Tomcat works 【发布时间】:2015-04-10 12:13:21 【问题描述】:

我们正在使用 Tomcat 6.0.35 在 OpenJDK IcedTea6 1.13.6 上运行 web 应用程序。对于 SSO,我们使用基于 OpenSAML 2.6.1 的 Spring 安全 SAML 扩展。

重新部署我们的应用程序(不重新启动 Tomcat)时,我得到一个 NoClassDefFoundError: org/bouncycastle/crypto/paddings/ISO10126d2Padding 很好地描述了here。从 Eclipse MAT 分析中,我收集到 BouncyCastleProvider 或 JCERSAPublicKey 正在阻止 WebappClassLoader 被 gc'ed。

如何配置 SAML 以便正确销毁所有(充气城堡)实例?我很难相信 SAML 的设计使得部署要求 Tomcat 重新启动。

我目前的配置: ...

<bean id="samlLogger" class="org.springframework.security.saml.log.SAMLDefaultLogger">
    <property name="logErrors" value="true"/>
    <property name="logMessages" value="true"/>
</bean>

<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="tenzingfaces" value="keyphrase"/>
        </map>
    </constructor-arg>
    <constructor-arg type="java.lang.String" value="tenzingfaces"/>
</bean>

<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
    <property name="defaultProfileOptions">
        <bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
            <property name="binding" value="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
            <property name="includeScoping" value="false"/>
        </bean>
    </property>
</bean>

<bean id="metadataDisplayFilter" class="org.springframework.security.saml.metadata.MetadataDisplayFilter"/>

<bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
    <property name="userDetails" ref="samlUserDetailService" />
    <property name="forcePrincipalAsString" value="false" />
</bean>

<bean id="samlUserDetailService" class="ch.umbrella.springframework.security.SamlUserDetailsServiceImpl" />

<bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>

<bean id="samlSuccessRedirectHandler" class="ch.umbrella.springframework.security.SsoAuthenticationSuccessHandler" >
    <property name="defaultTargetUrl" value="/main.html" />
    <property name="alwaysUseDefaultTargetUrl" value="false" />
    <property name="credentialsExpiredUrl" value="/credentialsexpired.html" />
</bean>
<bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationSuccessHandler" ref="samlSuccessRedirectHandler"/>
</bean>

<bean id="processor" class="org.springframework.security.saml.processor.SAMLProcessorImpl">
    <constructor-arg>
        <list>
            <ref bean="redirectBinding"/>
            <ref bean="postBinding"/>
        </list>
    </constructor-arg>
</bean>

<bean id="webSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerImpl"/>
<bean id="hokWebSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
<bean id="webSSOprofile" class="org.springframework.security.saml.websso.WebSSOProfileImpl"/>
<bean id="hokWebSSOProfile" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>

<bean id="postBinding" class="org.springframework.security.saml.processor.HTTPPostBinding">
    <constructor-arg ref="parserPool"/>
    <constructor-arg ref="velocityEngine"/>
</bean>

<bean id="velocityEngine" class="org.springframework.security.saml.util.VelocityFactory" factory-method="getEngine"/>

<bean id="redirectBinding" class="org.springframework.security.saml.processor.HTTPRedirectDeflateBinding">
    <constructor-arg ref="parserPool"/>
</bean>

<bean class="org.springframework.security.saml.SAMLBootstrap"/>

<bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" scope="singleton" init-method="initialize"/>
<bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder" scope="singleton"/>
...    

并且,在特定于暂存的文件中:

<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate" destroy-method="destroy">
                <constructor-arg>
                    <bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider" destroy-method="destroy">
                        <constructor-arg ref="timer1" />
                        <constructor-arg>
                            <bean class="org.opensaml.util.resource.ClasspathResource">
                                <constructor-arg value="/security/idp.xml"/>
                            </bean>
                        </constructor-arg>
                        <property name="parserPool" ref="parserPool"/>
                    </bean>
                </constructor-arg>
                <constructor-arg>
                    <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
                    </bean>
                </constructor-arg>
            </bean>
            <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate" destroy-method="destroy">
                <constructor-arg>
                    <bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider" destroy-method="destroy">
                        <constructor-arg ref="timer2" />
                        <constructor-arg>
                            <bean class="org.opensaml.util.resource.ClasspathResource">
                                <constructor-arg value="/security/localhost_sp.xml"/>
                            </bean>
                        </constructor-arg>
                        <property name="parserPool" ref="parserPool"/>
                    </bean>
                </constructor-arg>
                <constructor-arg>
                    <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
                        <property name="local" value="true"/>
                        <property name="securityProfile" value="metaiop"/>
                        <property name="sslSecurityProfile" value="pkix"/>
                        <property name="signMetadata" value="true"/>
                        <property name="signingKey" value="tenzingfaces"/>
                        <property name="encryptionKey" value="tenzingfaces"/>
                        <property name="requireArtifactResolveSigned" value="false" />
                        <property name="requireLogoutRequestSigned" value="false" />
                        <property name="requireLogoutResponseSigned" value="false" />
                        <property name="idpDiscoveryEnabled" value="false" />
                    </bean>
                </constructor-arg>
            </bean>
        </list>
    </constructor-arg>
    <property name="hostedSPName" value="https://hurricane.umbrellanet.ch/uf-test/saml/metadata" />
</bean>

谢谢 西蒙

【问题讨论】:

【参考方案1】:

如果您在战争中捆绑 bouncycastle 罐子,请不要这样做。而是将这些罐子放在 tomcat/lib 中。希望这会解决它。

【讨论】:

以上是关于OpenSAML / Spring 安全设置,因此在 Tomcat 上重新部署有效的主要内容,如果未能解决你的问题,请参考以下文章

OpenSaml3 文档

OpenSAML

由于 IP 和 SP 之间的时区差异导致的 Spring Saml 安全身份验证问题

SpringSecurity-SAML(OpenSAML):无法解组断言:获取 org.w3c.dom.DOMException:WRONG_DOCUMENT_ERR

Spring-SAML 的 SSL 配置问题

创建 QName 异常时,Opensaml unmarshallMessage 给出的 opensaml 本地部分不能为“null”