What is the correct way to add encryption / decryption in spring-ws (wss4j)?

I deployed 2 web applications, one representing a web service and the other representing a ws client. When you use SIGNING and TIMESTAMP-ing, everything works fine, a message with mail clicks (but I think that it does not override the standard 300s ttl), signs the message with its x509 certificate and sends it to ws. He, on the other hand, receives a message and is able to mark the timestamp and certificate / signature against trusted client certificates in his keystore.

The problem occurs when I add an encryption operation to my configuration. The client seems to be able to encrypt the message, but ws does not seem to be interested 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 to achieve timestamp, signing with x509 and encryption, again with x509?

part of the app-context server:

<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> 

The client basically uses the same configuration, except that it uses the server’s public key for encryption and its private key for decryption.

Keystores is fine, I think because signing works fine ... Everything that burns falls apart when I add an Encrypt action, part of the 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 need to somehow instruct ws to decrypt the SOAP body before it starts looking for the endpoint for the message, but I don't know how to do it. Suggestions?

+6
source share
2 answers

Since your comments were useful, but seemingly incomplete, I did the shooting with the answer in a bit more detail.

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

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

When the soap message is encrypted, the PayloadRootAnnotationMethodEndpointMapping value cannot display the soap message because the security interceptor did not yet have time to decrypt it. The solution is to replace @PayloadRoot with @SoapAction.

When a soap message is received, spring -ws will first call the LoadloadRootAnnotationMethodEndpointMapping command, and then SoapActionAnnotationMethodEndpointMapping. You can use both options for full compatibility with the spring client (axis, for example, or .net):

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

Last but not least, if you use a spring client with a secure soap message, spring does not automatically send soap action. Your server will not be able to match the message with soap with the corresponding action. To solve this problem, you should use WebServiceMessageCallback:

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

where is the class 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); } } } 
+6
source

this is because you did not define the securementEncryptionParts property. This forces the whole body to be encrypted and make this mistake.

0
source

Source: https://habr.com/ru/post/892818/


All Articles