我已经部署了2个Web应用程序,一个代表Web服务,另一个代表ws客户端。当使用SIGNING和TIMESTAMP-ing时,一切正常,客户端标记消息(但我认为他没有覆盖默认的300s ttl),用他的x509证书签名消息,并将其发送给ws。另一方面,他收集了消息,并且能够在其密钥库中对客户端可信证书进行时间戳和证书/签名的验证。
当我向我的配置添加加密操作时出现问题。客户端似乎能够加密消息,但似乎没有兴趣解密消息。他只看到
没有端点映射[SaajSoapMessage {http://www.w3.org/2001/04/xmlenc#}EncryptedData]
并抛出
WebServiceTransportException: Not Found [404] exception.
有人可以解释我需要做些什么来实现时间戳,使用x509进行签名和加密,再次使用x509?
服务器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>
客户端基本上使用相同的配置,除了他使用服务器公钥进行加密,以及使用他的私钥进行解密。
密钥库是好的,我猜,因为签名工作正常...当我添加加密操作时,一切都崩溃了,服务器日志的一部分说:
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主体,但我不知道如何。建议?
答案 0 :(得分:6)
由于您的评论很有帮助,但有点不完整,我拍了一些回答更多细节。
在spring教程中,使用@PayloadRoot注释端点方法:@PayloadRoot(localPart = "orderInput", namespace = "http://samples")
当soap消息未加密时,此方法正常。 PayloadRootAnnotationMethodEndpointMapping能够映射到soap消息到相应的方法。
当soap消息被加密时,PayloadRootAnnotationMethodEndpointMapping无法映射soap消息,因为安全拦截器还没有时间来解密它。解决方案是用@SoapAction替换@PayloadRoot。
当收到soap消息时,spring-ws首先调用PayloadRootAnnotationMethodEndpointMapping,然后调用SoapActionAnnotationMethodEndpointMapping。您可以使用它们以便与非弹簧客户端完全兼容(例如轴或.net):
@PayloadRoot(localPart = "orderInput", namespace = "http://samples")
@SoapAction("http://samples/order")
最后但并非最不重要:如果您使用带有安全肥皂消息的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);
}
}
}
答案 1 :(得分:0)
这是因为您没有定义securementEncryptionParts属性。它导致加密整个身体并导致此错误
答案 2 :(得分:0)
在触发@Endpoint之前,是否仍然需要解密请求?问题是客户端无法添加肥皂动作。