请帮助: 供应商需要签名的xml,并且在描述如何正确签名xml方面没有提供太多帮助。我正在发送以下xml:
@Slf4j
public class CustomRedirectFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_FORWARD_FILTER_ORDER;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
String requestUrl = ctx.getRequest().getRequestURL().toString();
if (shouldBeRedirected(requestUrl)) {
String redirectUrl = generateRedirectUrl(ctx.getRequest());
sendRedirect(ctx.getResponse(), redirectUrl);
}
return null;
}
private void sendRedirect(HttpServletResponse response, String redirectUrl){
try {
response.setHeader(HttpHeaders.LOCATION, redirectUrl);
response.setStatus(HttpStatus.MOVED_PERMANENTLY.value());
response.flushBuffer();
} catch (IOException ex) {
log.error("Could not redirect to: " + redirectUrl, ex);
}
}
private boolean shouldBeRedirected(String requestUrl) {
// your logic whether should we redirect request or not
return true;
}
private String generateRedirectUrl(HttpServletRequest request) {
String queryParams = request.getQueryString();
String currentUrl = request.getRequestURL().toString() + (queryParams == null ? "" : ("?" + queryParams));
// update url
return updatedUrl;
}
}
,并且我收到一条错误消息,指出存在肥皂错误SECU3504:数字签名验证失败。 ds:Signed Info签名的有效性:java.lang.NullPointerException。签名参考的有效性:#_2:是。 #_1:否。
这听起来像是我引用信封正文Id =“ _ 1”时出现问题。
这是我在标头中创建主体和安全性令牌引用之后用于签名xml的C#代码。
<SOAP-ENV:Envelope xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><wsse:SecurityTokenReference Id="_2"><wsse:Reference URI="#binarytoken" /></wsse:SecurityTokenReference></ds:KeyInfo><wsse:BinarySecurityToken EncodingType="wsse:Base64Binary" ValueType="wsse:X509v3" wsu:Id="binarytoken">removed for security</wsse:BinarySecurityToken><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI="#_2"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>b3U301pqu017IPMBNIZ04dybZ+A=</DigestValue></Reference><Reference URI="#_1"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>NLpGjn8jJ7RI/R4rVdiwZPRRyMU=</DigestValue></Reference></SignedInfo><SignatureValue>some signed value here</SignatureValue></Signature></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body wsu:Id="_1"><msg:CompanyMessage xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:msg="companyNameSpace"><msg:Header><msg:Verb>get</msg:Verb><msg:Noun>CompanyFunction</msg:Noun><msg:Revision>1</msg:Revision><msg:Source>COMPANY</msg:Source><msg:UserID>USER</msg:UserID><msg:MessageID>123456789</msg:MessageID><msg:ReplayDetection><wsu:Created>2018-07-27T02:20:39-05:00</wsu:Created><wsse:Nonce>65b9a415-19d9-4090-8520-e1de12cc9721</wsse:Nonce></msg:ReplayDetection></msg:Header></msg:CompanyMessage></SOAP-ENV:Body></SOAP-ENV:Envelope>
非常感谢您的协助。
答案 0 :(得分:1)
在为电信运营商工作时,我们有使用WS-Security且需要签名的类似服务。当我需要测试这些服务时,我遇到了同样的问题。当然,我们的合作伙伴也很难使用这些服务。
最后,我通过使用WCF使其正常工作(您至少需要.NET Framework 4.0):
第一步,您需要从提供的WSDL中导入Web服务描述,并对生成的代码进行更改:
您必须在ProtectionLevel = System.Net.Security.ProtectionLevel.Sign
上添加ServiceContratAttribute
,以告知WCF您需要对其进行签名:
[System.ServiceModel.ServiceContractAttribute(ProtectionLevel = System.Net.Security.ProtectionLevel.Sign, Namespace="http://ServiceProvider.someTelecom.fr/Services/Payment "
public interface GetPaymentPortType
{
…
}
然后您应该在app.config中使用以下customBinding
<customBinding>
<binding name="HTTPBinding_WSSecurity">
<security enableUnsecuredResponse="true" authenticationMode="MutualCertificate"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSignatureConfirmation="false">
<localClientSettings maxClockSkew="00:10:00" />
<localServiceSettings maxClockSkew="00:10:00" />
<secureConversationBootstrap />
</security>
<textMessageEncoding messageVersion="Soap11" />
<httpTransport />
</binding>
</customBinding>
最后,在致电Web服务之前,您还需要加载您的客户证书(以下.pfx格式的代码),以便对肥皂消息进行签名。
//Load the signature certificate
X509Certificate2 mycertificate = new X509Certificate2("SignatureCertificate.pfx", "[pfx protection password]");
//Create the wcf client from the given binding
MyServicePortTypeClient client = new MyServicePortTypeClient("HTTPBinding_WSSecurity");
client.Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri("http://xxxxxx/myService"), EndpointIdentity.CreateDnsIdentity("dns_name"));
//set the client ceritificate
client.ClientCredentials.ClientCertificate.Certificate = mycertificate;
//Call the service
client.Payment(xxx);
奖金: 如果使用的是自签名证书,请确保可以在服务提供商的服务器上验证该证书。否则,您应该使用提供商提供的证书。