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

问题描述 投票:7回答:3

我部署了两个web应用程序,一个代表web服务,另一个代表ws客户端。当使用 SIGNING 和 TIMESTAMP-ing 时,一切都很正常,客户端给消息盖章(但我认为他没有覆盖默认的 300s ttl),用他的 x509 证书签署消息,然后发送给 ws。另一方面,他接收到消息后,能够在他的keystore中根据客户的信任证书来验证时间戳和证书签名。

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

[SaajSoapMessage {http:/www.w3.org200104xmlenc#}EncryptedData] 

并抛出

WebServiceTransportException.Not Found[404]异常。Not Found [404] 异常。

谁能解释一下我需要做什么才能实现时间戳,用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.springframe]"。

DEBUG [org.springframework.ws.server.MessageTracing.recei ved] - 收到请求 [SaajSoapMessage {http:/www.w3.org200104xmlenc#}EncryptedData]DEBUG [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping] - 查找[{http:/www.w3.org200104xmlenc#}EncryptedData]的端点。 ws.soap.server.SoapMessageDisp atcher]-端点映射[org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping@30a14083]没有为请求找到映射...没有为[SaajSoapMessage {http:/www.w3.org200104xmlenc#}EncryptedData]org.springframework.ws.client.WebServiceTransportE xception.找到端点映射。Not Found [404]...

我想我必须以某种方式指示ws在开始寻找消息的端点之前解密SOAP body,但我不知道怎么做。有什么建议吗?

java web-services spring encryption spring-ws
3个回答
9
投票

由于你的评论很有帮助,但有点不完整,我采取了一个拍摄的回答与更多的细节。

在spring教程中,endpoint方法被注解为@PayloadRoot。@PayloadRoot(localPart = "orderInput", namespace = "http://samples")

当soap消息没有加密的时候,这就能正常工作。 PayloadRootAnnotationMethodEndpointMapping能够将soap消息映射到对应的方法中。

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

当收到 soap 消息时,spring-ws 会先调用 PayloadRootAnnotationMethodEndpointMapping,然后调用 SoapActionAnnotationMethodEndpointMapping。你可以同时使用这两个方法,以便与非spring客户端完全兼容(例如axis或.net)。

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

最后但并非最不重要。如果你使用的是带有安全soap消息的spring客户端,spring不会自动发送soap动作。你的服务器将无法将 soap 消息与相应的动作进行映射。为了解决这个问题,你应该使用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);
        }

    }
}

0
投票

发生这种情况是因为你没有定义securementEncryptionParts属性。它将导致整个主体加密,并产生以下错误。

© www.soinside.com 2019 - 2024. All rights reserved.