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

OpenSAML / Spring security setup so redeploy on Tomcat works

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

重新部署我们的应用程序时(无需重新启动 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>

谢谢 西蒙

如果您将 bouncycastle 罐子捆绑在 war 中,则不要那样做。而是将这些罐子放在 tomcat/lib 中。希望这能解决问题。