在 spring-ws (wss4j) 中添加加密/解密的正确方法是什么?

发布于 2024-11-23 18:06:14 字数 4165 浏览 1 评论 0原文

我部署了 2 个 Web 应用程序,一个代表 Web 服务,另一个代表 ws 客户端。当使用 SIGNING 和 TIMESTAMP-ing 时,一切正常,客户端标记消息(但我认为他不会覆盖默认的 300s ttl),用他的 x509 证书签署消息,并将其发送到 ws。另一方面,他接收消息并能够根据其密钥库中的客户端信任证书来验证时间戳和证书/签名。

当我将加密操作添加到我的配置中时出现问题。客户端似乎能够加密消息,但 ws 似乎不感兴趣解密消息。他只是看到没有端点映射

[SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData] 

并抛出异常,

WebServiceTransportException: Not Found [404] exception.

所以有人可以解释我需要做什么才能实现时间戳、使用 x509 签名和加密,再次使用 x509 吗?

服务器应用程序上下文的一部分:

<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"> 
        <!-- valiadation -->
        <property name="validationActions" value="Timestamp Signature Encrypt"/> 
        <property name="enableSignatureConfirmation" value="true"/> 
        <property name="validationSignatureCrypto"> 
            <ref bean="keystore"/> 
        </property> 
        <property name="validationDecryptionCrypto"> 
                <ref bean="keystore"/> 
        </property> 
        <property name="validationCallbackHandler"> 
            <bean class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler"> 
                <property name="privateKeyPassword" value="password"/> 
            </bean> 
        </property> 
         <!-- timestamp options -->
        <property name="timestampStrict" value="true"/> 
        <property name="timeToLive" value="30"/> 
        <property name="timestampPrecisionInMilliseconds" value="true"/> 
         <!-- signing and encryption -->
        <property name="securementActions" value="Timestamp Signature Encrypt"/> 
        <property name="securementUsername" value="wsserver"/> 
        <property name="securementPassword" value="password"/> 
        <property name="securementSignatureKeyIdentifier" value="DirectReference"/> 

        <property name="securementSignatureCrypto"> 
            <ref bean="keystore"/> 
        </property> 
        <property name="securementEncryptionUser" value="wsclient"/> 
        <property name="securementEncryptionCrypto"> 
            <ref bean="keystore"/> 
        </property>
</bean>
 <!-- keystore -->
<bean id="keystore" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean"> 
          <property name="keyStorePassword" value="password"/> 
          <property name="keyStoreLocation" value="WEB-INF/MyTruststore.jks"/> 
</bean>
<!-- interceptors -->
<sws:interceptors> 
<ref bean="wss4jSecurityInterceptor"/> 
<bean id="validatingInterceptor" 
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor"> 
  <property name="schema" value="/WEB-INF/person.xsd"/>
  <property name="validateRequest" value="true"/> 
  <property name="validateResponse" value="true"/> 
</bean> 
    <bean id ="loggingInterceptor"    class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"> 
    </bean> 
    </sws:interceptors>

客户端基本上使用相同的配置,只是他使用服务器公钥进行加密,并使用他的私钥进行解密。

我猜密钥库没问题,因为签名工作正常...当我添加加密操作时,一切都崩溃了,服务器日志的一部分说:

DEBUG [org.springframework.ws.server.MessageTracing.recei ved] - Received request [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping] - Looking up endpoint for [{http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Endpoint mapping [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping@30a14083] has no mapping for request
...
No endpoint mapping found for [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
org.springframework.ws.client.WebServiceTransportE xception: Not Found [404]
...

我想我必须以某种方式指示 ws 在开始寻找端点之前解密 SOAP 主体发消息,但不知道怎么发建议?

I have deployed 2 web apps, one representing web service and other representing ws client. When using SIGNING and TIMESTAMP-ing, everything works fine, client stamps message(but i think that he doesn't override the default 300s ttl), signs the message with his x509 cert, and sends it to ws. He, in the other hand, recives message and is able to valiadate timestamp and certificate/signature against clients trusted cert in his keystore.

Problem arises when i add Encrypt operation to my configuration. Client seems to be able to encrypt the message, but ws seems not to be intrested in decrypting the message. He just sees that there is no endpoint mapping for

[SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData] 

and throws

WebServiceTransportException: Not Found [404] exception.

SO can someone explain what I need to do in order to achieve timestamping,signing with x509 and encryption, again with x509?

part of server app-context:

<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"> 
        <!-- valiadation -->
        <property name="validationActions" value="Timestamp Signature Encrypt"/> 
        <property name="enableSignatureConfirmation" value="true"/> 
        <property name="validationSignatureCrypto"> 
            <ref bean="keystore"/> 
        </property> 
        <property name="validationDecryptionCrypto"> 
                <ref bean="keystore"/> 
        </property> 
        <property name="validationCallbackHandler"> 
            <bean class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler"> 
                <property name="privateKeyPassword" value="password"/> 
            </bean> 
        </property> 
         <!-- timestamp options -->
        <property name="timestampStrict" value="true"/> 
        <property name="timeToLive" value="30"/> 
        <property name="timestampPrecisionInMilliseconds" value="true"/> 
         <!-- signing and encryption -->
        <property name="securementActions" value="Timestamp Signature Encrypt"/> 
        <property name="securementUsername" value="wsserver"/> 
        <property name="securementPassword" value="password"/> 
        <property name="securementSignatureKeyIdentifier" value="DirectReference"/> 

        <property name="securementSignatureCrypto"> 
            <ref bean="keystore"/> 
        </property> 
        <property name="securementEncryptionUser" value="wsclient"/> 
        <property name="securementEncryptionCrypto"> 
            <ref bean="keystore"/> 
        </property>
</bean>
 <!-- keystore -->
<bean id="keystore" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean"> 
          <property name="keyStorePassword" value="password"/> 
          <property name="keyStoreLocation" value="WEB-INF/MyTruststore.jks"/> 
</bean>
<!-- interceptors -->
<sws:interceptors> 
<ref bean="wss4jSecurityInterceptor"/> 
<bean id="validatingInterceptor" 
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor"> 
  <property name="schema" value="/WEB-INF/person.xsd"/>
  <property name="validateRequest" value="true"/> 
  <property name="validateResponse" value="true"/> 
</bean> 
    <bean id ="loggingInterceptor"    class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"> 
    </bean> 
    </sws:interceptors>

Client basicly uses the same config, except that he uses server public key for encryption, and his private key for decryption.

Keystores are ok, i guess, because signing works ok...Everything juust falls apart when i add Encrypt action, part of server log says:

DEBUG [org.springframework.ws.server.MessageTracing.recei ved] - Received request [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping] - Looking up endpoint for [{http://www.w3.org/2001/04/xmlenc#}EncryptedData]
DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Endpoint mapping [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping@30a14083] has no mapping for request
...
No endpoint mapping found for [SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
org.springframework.ws.client.WebServiceTransportE xception: Not Found [404]
...

I think I must somehow instruct ws to decrypt SOAP body before it starts to look for an endpoint for message,but I don't know how. Suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沙沙粒小 2024-11-30 18:06:14

由于您的评论很有帮助,但有点不完整,因此我采取了一些更详细的回答。

在spring教程中,端点方法用@PayloadRoot注释: @PayloadRoot(localPart = "orderInput", namespace = "http://samples")

当soap消息未加密时,这可以正常工作。 PayloadRootAnnotationMethodEndpointMapping能够将soap消息映射到相应的方法。

当肥皂消息被加密时,PayloadRootAnnotationMethodEndpointMapping无法映射肥皂消息,因为安全拦截器还没有时间解密它。解决方案是将@PayloadRoot 替换为@SoapAction。

当接收到soap消息时,spring-ws首先调用PayloadRootAnnotationMethodEndpointMapping,然后调用SoapActionAnnotationMethodEndpointMapping。您可以同时使用两者,以便与非 Spring 客户端(例如 axis 或 .net)完全兼容:

@PayloadRoot(localPart = "orderInput", namespace = "http://samples")
@SoapAction("http://samples/order") 

最后但并非最不重要的一点是:如果您使用带有安全肥皂消息的 Spring 客户端,Spring 不会自动发送肥皂操作。您的服务器将无法将肥皂消息映射到适当的操作。为了解决这个问题,您应该使用WebServiceMessageCallback:

ClientMessageCallBack callBack = new ClientMessageCallBack(
"http://samples/order");                    
Object output = wsTemplate.marshalSendAndReceive(inputObject, callBack);

其中ClientMessageCallBack类是

public final class ClientMessageCallBack 
    implements WebServiceMessageCallback {

    /**the soapAction to be appended to the soap message.*/
    private String soapAction;

    /**constructor.
     * @param action the soapAction to be set.*/
    public ClientMessageCallBack(final String action) {
        this.soapAction = action;
    }

    @Override
    public void doWithMessage(final WebServiceMessage message) 
            throws IOException, TransformerException {

        if (message instanceof SoapMessage) {
            SoapMessage soapMessage = (SoapMessage) message;
            soapMessage.setSoapAction(soapAction);
        }

    }
}

Since your comments were helpful but kind of incomplete, I took a shoot of answering with a bit more of a detail.

In the spring tutorial, the endpoint method is annotated with @PayloadRoot: @PayloadRoot(localPart = "orderInput", namespace = "http://samples")

This works fine when the soap message is not encrypted. PayloadRootAnnotationMethodEndpointMapping is able to map to soap message to the corresponding method.

When the soap message is encrypted, the PayloadRootAnnotationMethodEndpointMapping is unable to map the soap message because The security interceptor did not have yet the time to decipher it. The solution is to replace @PayloadRoot with @SoapAction.

When a soap message is received, spring-ws calls first the PayloadRootAnnotationMethodEndpointMapping then SoapActionAnnotationMethodEndpointMapping. You can use both in order to be full compatible with non-spring client (axis for example or .net):

@PayloadRoot(localPart = "orderInput", namespace = "http://samples")
@SoapAction("http://samples/order") 

Last but not least: If you are using a spring client with secured soap message, spring does not send soap action automatically. Your server will not be able to map the soap message with the appropriate action. In order to solve this problem, you should use a WebServiceMessageCallback:

ClientMessageCallBack callBack = new ClientMessageCallBack(
"http://samples/order");                    
Object output = wsTemplate.marshalSendAndReceive(inputObject, callBack);

where ClientMessageCallBack class is

public final class ClientMessageCallBack 
    implements WebServiceMessageCallback {

    /**the soapAction to be appended to the soap message.*/
    private String soapAction;

    /**constructor.
     * @param action the soapAction to be set.*/
    public ClientMessageCallBack(final String action) {
        this.soapAction = action;
    }

    @Override
    public void doWithMessage(final WebServiceMessage message) 
            throws IOException, TransformerException {

        if (message instanceof SoapMessage) {
            SoapMessage soapMessage = (SoapMessage) message;
            soapMessage.setSoapAction(soapAction);
        }

    }
}
独孤求败 2024-11-30 18:06:14

发生这种情况是因为您没有定义 securementEncryptionParts 属性。它导致加密整个主体并导致此错误

this happens because you did not defined securementEncryptionParts property. It causes to encrypt whole body and made to this Error

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文