验证 SOAP 响应 xml 时间戳和签名 X509 spring-ws-security
Validate SOAP response xml timestamp and signature X509 spring-ws-security
我是 spring-ws-security 的新手,几乎阅读了所有关于 google 和堆栈跟踪的文章,但无法正常工作。
我需要验证响应 XML 签名、时间戳,然后检索数据。当我跳过验证时,没有问题,但是当我添加验证代码时,我收到错误:
警告:无法验证请求:签名或解密无效;嵌套异常是org.apache.ws.security.WSSecurityException:签名或解密无效
@Configuration
public class SoapClientConfig {
final String generatedResource = "packageName";
@Bean
public KeyStoreCallbackHandler securityCallbackHandler() {
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("serverkeystorepassword");
return callbackHandler;
}
@Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature");
securityInterceptor.setSecurementUsername("clientkeystoreusername");
securityInterceptor.setSecurementPassword("clientkeystorepassword");
//sign both body and timestamp - default body will be signed
securityInterceptor.setSecurementSignatureParts("{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
//This will generate binarySecurityToken in header
securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
securityInterceptor.setSecurementSignatureCrypto(getRequestCryptoBean().getObject());
//This is validation code, which is not validating response.
securityInterceptor.setValidationActions("Timestamp Signature");
securityInterceptor.setValidationSignatureCrypto(getResponseCryptoBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getRequestCryptoBean() throws IOException, URISyntaxException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("clientkeystorepassword");
cryptoFactoryBean.setKeyStoreLocation("client.jks");
return cryptoFactoryBean;
}
@Bean
public CryptoFactoryBean getResponseCryptoBean() throws Exception {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setDefaultX509Alias("1");
cryptoFactoryBean.setKeyStorePassword("serverkeystorepassword");
cryptoFactoryBean.setKeyStoreLocation("server.jks");
cryptoFactoryBean.afterPropertiesSet();
return cryptoFactoryBean;
}
@Bean
public Jaxb2Marshaller getMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedResource);
return marshaller;
}
@Bean
public Card getAvailableCardsClient() throws Exception {
Card memberCard = new Card();
memberCard.setMarshaller(getMarshaller());
memberCard.setUnmarshaller(getMarshaller());
//Set timeout for soap service
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
sender.setConnectionTimeout(2000);
sender.setReadTimeout(2000);
memberCard.setMessageSender(sender);
//end timeout
memberCard.setDefaultUri("url");
//add interceptor for adding and validating signature
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor()};
memberCard.setInterceptors(interceptors);
return memberCard;
}
}
** server.jks 包含服务器的 public 密钥。而且此身份验证是 X509 证书。
请帮我弄清楚如何验证响应。
我找到了我的解决方案并发布给同一条船上的其他人。
在我的场景中,因为我必须使用两个不同的证书(server.jks、client.jks)来进行请求和响应验证;我不能为此使用相同的拦截器。我最终创建了两种不同的拦截器,一种用于请求,一种用于响应。
这是工作代码副本:
@Configuration
public class SoapClientConfig {
@Bean
public KeyStoreCallbackHandler securityCallbackHandler() throws Exception {
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setSymmetricKeyPassword("serverPassword");
return callbackHandler;
}
@Bean
public Wss4jSecurityInterceptor securityInterceptor() throws IOException, Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature");
securityInterceptor.setSecurementUsername("clientAias");
securityInterceptor.setSecurementPassword("clientPassword");
//sign both body and timestamp - default body will be signed
securityInterceptor.setSecurementSignatureParts("{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
//This will generate binarySecurityToken in header
securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
securityInterceptor.setSecurementSignatureCrypto(getRequestCryptoBean().getObject());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getRequestCryptoBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("clientPassword");
cryptoFactoryBean.setKeyStoreLocation("clientCertLoc");
return cryptoFactoryBean;
}
@Bean
public Wss4jSecurityInterceptor responseSecurityInterceptor() throws IOException, Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
securityInterceptor.setValidationActions("Timestamp Signature");
securityInterceptor.setValidationSignatureCrypto(getResponseCryptoBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getResponseCryptoBean() throws Exception {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStoreLocation("serverCertLoc");
cryptoFactoryBean.setDefaultX509Alias("serverAlias");
cryptoFactoryBean.setKeyStorePassword("serverPassword");
cryptoFactoryBean.afterPropertiesSet();
return cryptoFactoryBean;
}
@Bean
public Jaxb2Marshaller getMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedResource);
return marshaller;
}
@Bean
public WebServiceClass getPojoClassMethod() throws ConnectException, Exception {
WebServiceClass pClass= new WebServiceClass();
pClass.setMarshaller(getMarshaller());
pClass.setUnmarshaller(getMarshaller());
//Set timeout for soap service
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
int timeout;
if (null == stringFromEnvironmentOrIllegalStateException(env, timeoutInMs)) {
timeout = 10000;
} else {
timeout = Integer.parseInt(stringFromEnvironmentOrIllegalStateException(env, timeoutInMs));
}
sender.setConnectionTimeout(timeout);
sender.setReadTimeout(timeout);
pClass.setMessageSender(sender);
//end timeout config
pClass.setDefaultUri("actionURL");
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor(), responseSecurityInterceptor()};
pClass.setInterceptors(interceptors);
return pClass;
}
}
我是 spring-ws-security 的新手,几乎阅读了所有关于 google 和堆栈跟踪的文章,但无法正常工作。
我需要验证响应 XML 签名、时间戳,然后检索数据。当我跳过验证时,没有问题,但是当我添加验证代码时,我收到错误:
警告:无法验证请求:签名或解密无效;嵌套异常是org.apache.ws.security.WSSecurityException:签名或解密无效
@Configuration
public class SoapClientConfig {
final String generatedResource = "packageName";
@Bean
public KeyStoreCallbackHandler securityCallbackHandler() {
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("serverkeystorepassword");
return callbackHandler;
}
@Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature");
securityInterceptor.setSecurementUsername("clientkeystoreusername");
securityInterceptor.setSecurementPassword("clientkeystorepassword");
//sign both body and timestamp - default body will be signed
securityInterceptor.setSecurementSignatureParts("{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
//This will generate binarySecurityToken in header
securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
securityInterceptor.setSecurementSignatureCrypto(getRequestCryptoBean().getObject());
//This is validation code, which is not validating response.
securityInterceptor.setValidationActions("Timestamp Signature");
securityInterceptor.setValidationSignatureCrypto(getResponseCryptoBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getRequestCryptoBean() throws IOException, URISyntaxException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("clientkeystorepassword");
cryptoFactoryBean.setKeyStoreLocation("client.jks");
return cryptoFactoryBean;
}
@Bean
public CryptoFactoryBean getResponseCryptoBean() throws Exception {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setDefaultX509Alias("1");
cryptoFactoryBean.setKeyStorePassword("serverkeystorepassword");
cryptoFactoryBean.setKeyStoreLocation("server.jks");
cryptoFactoryBean.afterPropertiesSet();
return cryptoFactoryBean;
}
@Bean
public Jaxb2Marshaller getMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedResource);
return marshaller;
}
@Bean
public Card getAvailableCardsClient() throws Exception {
Card memberCard = new Card();
memberCard.setMarshaller(getMarshaller());
memberCard.setUnmarshaller(getMarshaller());
//Set timeout for soap service
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
sender.setConnectionTimeout(2000);
sender.setReadTimeout(2000);
memberCard.setMessageSender(sender);
//end timeout
memberCard.setDefaultUri("url");
//add interceptor for adding and validating signature
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor()};
memberCard.setInterceptors(interceptors);
return memberCard;
}
}
** server.jks 包含服务器的 public 密钥。而且此身份验证是 X509 证书。 请帮我弄清楚如何验证响应。
我找到了我的解决方案并发布给同一条船上的其他人。
在我的场景中,因为我必须使用两个不同的证书(server.jks、client.jks)来进行请求和响应验证;我不能为此使用相同的拦截器。我最终创建了两种不同的拦截器,一种用于请求,一种用于响应。
这是工作代码副本:
@Configuration
public class SoapClientConfig {
@Bean
public KeyStoreCallbackHandler securityCallbackHandler() throws Exception {
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setSymmetricKeyPassword("serverPassword");
return callbackHandler;
}
@Bean
public Wss4jSecurityInterceptor securityInterceptor() throws IOException, Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature");
securityInterceptor.setSecurementUsername("clientAias");
securityInterceptor.setSecurementPassword("clientPassword");
//sign both body and timestamp - default body will be signed
securityInterceptor.setSecurementSignatureParts("{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
//This will generate binarySecurityToken in header
securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
securityInterceptor.setSecurementSignatureCrypto(getRequestCryptoBean().getObject());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getRequestCryptoBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("clientPassword");
cryptoFactoryBean.setKeyStoreLocation("clientCertLoc");
return cryptoFactoryBean;
}
@Bean
public Wss4jSecurityInterceptor responseSecurityInterceptor() throws IOException, Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
securityInterceptor.setValidationActions("Timestamp Signature");
securityInterceptor.setValidationSignatureCrypto(getResponseCryptoBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
@Bean
public CryptoFactoryBean getResponseCryptoBean() throws Exception {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStoreLocation("serverCertLoc");
cryptoFactoryBean.setDefaultX509Alias("serverAlias");
cryptoFactoryBean.setKeyStorePassword("serverPassword");
cryptoFactoryBean.afterPropertiesSet();
return cryptoFactoryBean;
}
@Bean
public Jaxb2Marshaller getMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(generatedResource);
return marshaller;
}
@Bean
public WebServiceClass getPojoClassMethod() throws ConnectException, Exception {
WebServiceClass pClass= new WebServiceClass();
pClass.setMarshaller(getMarshaller());
pClass.setUnmarshaller(getMarshaller());
//Set timeout for soap service
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
int timeout;
if (null == stringFromEnvironmentOrIllegalStateException(env, timeoutInMs)) {
timeout = 10000;
} else {
timeout = Integer.parseInt(stringFromEnvironmentOrIllegalStateException(env, timeoutInMs));
}
sender.setConnectionTimeout(timeout);
sender.setReadTimeout(timeout);
pClass.setMessageSender(sender);
//end timeout config
pClass.setDefaultUri("actionURL");
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor(), responseSecurityInterceptor()};
pClass.setInterceptors(interceptors);
return pClass;
}
}