java - 有人在 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
对有关密钥库的信息的相同期望,但也许它可能是相关的:
- 使用 keytool 生成(不幸的是我不记得该命令)
- 公钥类型和大小:DSA 2048 位签名算法:
- SHA256WITHDSA 指纹 SHA-1
- 37:E8:E0:B7:DD:7E:7A:33:43:F8:9D:06:6D:20:1E:BE:B7:63:3A:B9
解决方案
推荐阅读
- ios - 在 iOS 中断开连接后,Spotify AppRemote 不会重新连接
- javascript - 如何在 weback.config.js 字符串中转义感叹号,以免导致 Terser 出错
- php - 在 PHP 中将字符串转换为 UTF-8
- reactjs - 从深度嵌套的组件更新状态而不重新渲染父组件
- arrays - 是否可以从列中的列表中加入或合并或合并值以生成动态公式
- c# - 使用 Json.net 自定义序列化
- c# - 从函数返回具有基类约束的泛型类型,而无需在 C# 中进行强制转换
- r - NA 如果值包含在 NA 之间
- r - 在 R 中使用 lapply 绘制多个数据帧
- javascript - Javascript未向php提交数据