2011-07-15 65 views
6

我部署了2个Web应用程序,一个代表Web服务,另一个代表Web客户端。当使用SIGNING和TIMESTAMP-ing时,一切正常,客户端邮戳消息(但我认为他不覆盖默认的300s ttl),用他的x509证书签名消息,并将其发送给ws。另一方面,他可以回复信息,并且能够在他的密钥库中验证客户端可信证书的时间戳和证书/签名。在spring-ws(wss4j)中添加加密/解密的正确方法是什么?

当我将加密操作添加到我的配置时出现问题。客户端似乎能够加密该消息,但似乎并不需要解密该消息。他只是看到有对

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

没有终点的映射,并抛出

 
WebServiceTransportException: Not Found [404] exception. 

SO有人可以解释我需要什么,以实现时间戳的事,与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> 

客户basicly使用相同的配置,不同的是他使用服务器的公钥进行加密,以及他对解密私钥。

密钥库都OK,我猜,因为签约的作品确定... juust分崩离析当我添加加密行动一切,服务器日志的一部分说:

 
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 [email protected]] 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主体在开始寻找消息的端点之前,但我不知道如何。建议?

+1

我解决了这个问题,好吧,有点。 事情是,我用@PayloadRoot注释,但我的payloadRoot从来没有任何东西,我的应用程序可以映射到一个端点..它只是EncryptedData。 当我将ann更改为@ SoapAction,并将WebServiceMessageCallback()接口添加到客户端的marshalSendAndReceive()时,Web服务认为他没有映射EncryptedData有效内容,因此他寻找使用SoapActionAnnotationMethodEndpointMapping进行映射并找到一个映射。 比服务器发现请求映射时,他解密SOAP body.....并发现PayloadRoot在那里:) – mare

+0

请关闭此问题! –

+0

在服务器应用程序环境中,您在哪里指定解密和签名的密钥别名? – WarLord

回答

6

由于您的评论有帮助,但有点不完整,我拍了一个更详细的回答。

在弹簧教程,端点方法都被注解@PayloadRoot:@PayloadRoot(localPart = "orderInput", namespace = "http://samples")

当未加密的SOAP消息这工作得很好。 PayloadRootAnnotationMethodEndpointMapping能够映射到肥皂消息到相应的方法。

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

当收到soap消息时,spring-ws首先调用PayloadRootAnnotationMethodEndpointMapping,然后SoapActionAnnotationMethodEndpointMapping。你可以为了同时使用是完全非弹性的客户端(轴例如或.net)兼容:

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

最后但并非最不重要的:如果你使用的是有担保的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

thx很棒!而不是你的ClientMessageCallBack,我用.marshalSendAndReceive(request,new SoapActionCallback(“http://spring.io/guides/gs-producing-web-service”)); – Janiiik

0

出现这种情况,因为你没有定义securementEncryptionParts属性。它导致加密整个身体,并做出此错误

相关问题