首页 > 解决方案 > 有人在 Spring Boot 应用程序中通过 SAMLCallbackHandler 成功地将 Spring.WS 的 Wss4jSecurityInterceptor 用于 SAML 安全性吗?

问题描述

是否有使用经验的人Wss4jSecurityInterceptor能够帮助确定我们是否在为 SOAP 调用的安全标头提供断言的 SAMLCallbackHandler 方面做错了什么?

具体来说:org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor

语境:

我们正在使用 Spring Boot + Spring Integration 构建服务总线,它需要能够使用和生成使用 SAML 签名的请求,而不是在 SSO 的上下文中。我们选择了 Wss4jSecurityInterceptor 来使用 SAML 验证和签署 SOAP 请求。我们将拦截器直接应用于 Spring Webservices,而不依赖于 Spring Integration。

我们目前在签名过程中遇到问题。我们有验证和签名工作,但没有断言应用于传出消息。这要求我们使用安全操作“SAMLTokenSigned”,该操作需要拦截器的 CallbackHandler(SAMLCallbackHandler)。

到目前为止,我们还没有找到此类 SAMLCallbackHandler 的现有实现或好的示例。我们发现的结果乏善可陈,并导致我们走上一条漫长的道路,即通过调试“猜测”处理程序缺少什么。在这一点上,我们似乎走错了路,而且我们错过了一些东西。我们正在做的并不是完全新颖的工作。

Wss4jSecurityInterceptor 的设置如下所示。

@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor(){

    Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();

    // The action SAMLTokenSigned requires us to use SAMLCallbackk
    interceptor.setSecurementActions("Signature SAMLTokenSigned");

    interceptor.setSecurementSignatureCrypto(keystoreCrypto());
    interceptor.setSecurementUsername("client");
    interceptor.setSecurementPassword("password");
    interceptor.setSecurementSignatureDigestAlgorithm("http://www.w3.org/2007/05/xmldsig-more#sha3-256");
    interceptor.setSecurementSignatureAlgorithm("http://www.w3.org/2009/xmldsig11#dsa-sha256");

    SAML2CallbackHandler saml2CallbackHandler = new SAML2CallbackHandler(); // implements CallbackHandler
    saml2CallbackHandler.crypto = keystoreCrypto(); // using the same keystore for the issuer
    interceptor.setSecurementSamlCallbackHandler(saml2CallbackHandler);

    // we ignore validationActions for now. e.g. interceptor.setValidationActions("Signature");

    return interceptor;
}

public Crypto keystoreCrypto(){
    CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();

    try{
        cryptoFactoryBean.setKeyStoreLocation( new ClassPathResource("saml-keystore.jks"));
        cryptoFactoryBean.setKeyStorePassword("password");
        return cryptoFactoryBean.getObject();
    }
    catch(Exception e){}

    return null;
}

我们的 SAML2Callback 处理程序深受https://github.com/jaminh/spring-saml-example-war/blob/master/src/test/java/org/apache/ws/security/common/SAML2CallbackHandler.java的启发,但我们不得不处理我们在 maven-repositories 上找不到的库,这带来了一系列小问题。我可以根据要求提供我们的版本,但它有点乱。

虽然我不希望它提供太多,但这里是在编写时为代码引发的异常的 Stacktrace:

Original Exception was org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:577) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleResponse(AbstractWsSecurityInterceptor.java:157) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.triggerHandleResponse(MessageDispatcher.java:371) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:239) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:176) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:89) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293) ~[spring-ws-core-3.0.8.RELEASE.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.5.RELEASE.jar:5.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.apache.wss4j.common.ext.WSSecurityException: Error when signing the SAML token: 
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:133) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.handler.WSHandler.doSenderAction(WSHandler.java:238) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.springframework.ws.soap.security.wss4j2.Wss4jHandler.doSenderAction(Wss4jHandler.java:63) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    at org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor.secureMessage(Wss4jSecurityInterceptor.java:574) ~[spring-ws-security-3.0.9.RELEASE.jar:na]
    ... 45 common frames omitted
Caused by: org.apache.wss4j.common.ext.WSSecurityException: No certificates were found for SAML signature
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.prepare(WSSecSignatureSAML.java:258) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.saml.WSSecSignatureSAML.build(WSSecSignatureSAML.java:110) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    at org.apache.wss4j.dom.action.SAMLTokenSignedAction.execute(SAMLTokenSignedAction.java:125) ~[wss4j-ws-security-dom-2.2.3.jar:2.2.3]
    ... 48 common frames omitted

对有关密钥库的信息的相同期望,但也许它可能是相关的:

标签: javaspringspring-bootsaml-2.0wss4j

解决方案


推荐阅读