我需要创建一个 wcf 客户端来调用我无法控制的服务。
我得到了一个 wsdl 和一个工作的 soapui 项目。
该服务同时使用用户名/密码和 x509 证书。
更新
我现在了解问题所在,但仍不确定我需要采取哪些步骤才能创建所需的消息,因此非常感谢任何帮助。
我需要同时签署 UsernameToken 和 SecurityTokenReference。
我必须创建自定义绑定的代码已从这篇文章中删除,因为它不再使用。我不再将 SecurityBindingElement 添加到绑定中,而是添加了一个将安全元素写入标头的新行为。
因此,安全节点是通过继承 SignedXml 类、添加签名引用然后调用 ComputeSignature 以在 Security 标头中创建 Signature 节点来从头开始创建的。
您需要将 xml 传递给 SignedXml 构造函数才能使其正常工作。传递 UsernameToken 没有问题,这似乎已正确签名。
问题是 SecurityTokenReference 仅在调用 ComputeSignature() 时创建,因此我无法向此元素添加签名引用,因为它在需要时不存在(在 SignedXml 的重写 GetIdElement 方法中在 ComputeSignature() 之前调用
我用来创建签名块以插入到安全标头中的代码如下
string certificatePath = System.Windows.Forms.Application.StartupPath + "\\" + "Certs\\sign-and- enc.p12";
XmlDocument xd = new XmlDocument();
xd.LoadXml(xml);
// Set Certificate
System.Security.Cryptography.X509Certificates.X509Certificate2 cert = new X509Certificate2(certificatePath, "password");
MySignedXml signedXml = new MySignedXml(xd);
signedXml.SigningKey = cert.PrivateKey;
// Create a new KeyInfo object.
KeyInfo keyInfo = new KeyInfo();
keyInfo.Id = "";
MemoryStream keyInfoStream = new MemoryStream();
XmlWriter keyInfoWriter = XmlWriter.Create(keyInfoStream);
WSSecurityTokenSerializer.DefaultInstance.WriteKeyIdentifierClause(keyInfoWriter, new LocalIdKeyIdentifierClause("token_reference", typeof(X509SecurityToken)));
keyInfoWriter.Flush();
keyInfoStream.Position = 0;
XmlDocument keyInfoDocument = new XmlDocument();
keyInfoDocument.Load(keyInfoStream);
XmlAttribute attrib = keyInfoDocument.CreateAttribute("ValueType");
attrib.InnerText = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
keyInfoDocument.ChildNodes[1].ChildNodes[0].Attributes.Append(attrib);
KeyInfoNode keyInfoNode = new KeyInfoNode();
keyInfoNode.LoadXml(keyInfoDocument.DocumentElement);
keyInfo.AddClause(keyInfoNode);
// Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyInfo;
// Need to use External Canonicalization method.
signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "#UsernameToken-1";
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
env.Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference.AddTransform(env);
reference.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
signedXml.AddReference(reference);
Reference reference2 = new Reference();
reference2.Uri = "#token_reference";
XmlDsigEnvelopedSignatureTransform env2 = new XmlDsigEnvelopedSignatureTransform();
env2.Algorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference2.AddTransform(env2);
reference2.DigestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
signedXml.AddReference(reference2);
// Add the Signature Id
signedXml.Signature.Id = "MYSIG_ID";
// Compute the signature.
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
其中 xml 变量是 UsernameToken xml 字符串,而 MySignedXml 类是一个子类 SignedXml,其中 GetIdElement 方法被覆盖(试图找到并正确地重新释放不存在的 SecurityTokenReference)
我现在花了几天时间研究和测试这个,不幸的是,提供服务的公司没有任何帮助——但我需要使用他们的服务。
完整的工作肥皂消息(soapUI 项目)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:XXXXX">
<soapenv:Header xmlns:ebxml="http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/">
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="CertId-D05E596B5ABC341FEB13505090224061" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">MIIEnDCCBAWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBxDELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxHjAcBgNVBAMTFWRldmNhLmIyYi5pcmQuZ292dC5uejEXMBUGA1UEKRMORGV2ZWxvcG1lbnQgQ0ExKDAmBgkqhkiG9w0BCQEWGWNocmlzLnNjaHVsdHpAaXJkLmdvdnQubnowHhcNMTEwOTE1MDIwNjIwWhcNMjEwOTEyMDIwNjIwWjCByTELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxJTAjBgNVBAMTHHNpZ24tYW5kLWVuYy5kZXYuaXJkLmdvdnQubnoxFTATBgNVBCkTDHNpZ24tYW5kLWVuYzEoMCYGCSqGSIb3DQEJARYZY2hyaXMuc2NodWx0ekBpcmQuZ292dC5uejCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAykyZHVnXjsG220zB3kNOsGBeGP2rdNbLlIqW1D8yZO1fcj3/RhRiqsopbUrb8AU1ClpfhbH2K68kg7V91VAY0qrwNxP+pPPo1vYKMU6pT38qJGQzffr+iV2BCJshZvSk9E7QSWO5mFNstdg19xc+5ST1Lgb3fefuRG2KZVxPx0sCAwEAAaOCAZUwggGRMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDQGCWCGSAGG+EIBDQQnFiVFYXN5LVJTQSBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSczRKXKPe3Sin7eFrVXfI7MXckzzCB+QYDVR0jBIHxMIHugBSLWxPSZd9otEj16vhLyovMCI9OMaGByqSBxzCBxDELMAkGA1UEBhMCTloxDTALBgNVBAgTBFdHVE4xEzARBgNVBAcTCldlbGxpbmd0b24xGDAWBgNVBAoTD0lSRFN0dWR5bGlua0IyQjEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxHjAcBgNVBAMTFWRldmNhLmIyYi5pcmQuZ292dC5uejEXMBUGA1UEKRMORGV2ZWxvcG1lbnQgQ0ExKDAmBgkqhkiG9w0BCQEWGWNocmlzLnNjaHVsdHpAaXJkLmdvdnQubnqCCQDL/qDdlx2j6DATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEAS4ZPIVVpgTOGN4XcIC3SiYlxF8wYg7qnUhH5wJsAD3VCKfj68j9FSJtdBWLlWvvRxEoDP2lZ0IbFl6Rjnl+2ibzFnyac2G1AVm5mwPrNKHBQJ9J5eDJi0iUVY7Wphz86tKnqj34GvlHPNXmrF7oGEcDhPwK0T8zRdE/pvKIUiJc=</wsse:BinarySecurityToken>
<ds:Signature Id="Signature-2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#CertId-D05E596B5ABC341FEB13505090224061">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>3iVAUEAt8vAb7Ku+jf2gwSkSm0Q=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#UsernameToken-1">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>r4HLEAWJldJwmEmcAqV6Y8rnTPE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
YGh2I3VcukqjT0O7hKItiykWN5tlID18ZXRCwQjXriHmnVsO4wGcHjWfmhuNDecq+xRN+SjG8E7M
2Rx/5/BbFKbVlNOkQOSbSxIs1YT9GaThK16pMrX5KRkkJme1W3R0pGIIQh6gGRSUf79RZUIYxyVl
LqdIe561TXXDdtbt/6Q=
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-D05E596B5ABC341FEB13505090224372">
<wsse:SecurityTokenReference wsu:Id="STRId-D05E596B5ABC341FEB13505090224373" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Reference URI="#CertId-D05E596B5ABC341FEB13505090224061" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsse:UsernameToken wsu:Id="UsernameToken-1" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>XXXXXX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">XXXXXXX</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<ebxml:Messaging xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ebxml:UserMessage>
<ebxml:MessageInfo>
<ebxml:Timestamp>2002-02-02T14:18:02.0Z</ebxml:Timestamp>
<ebxml:MessageId>bf9433d9-c6e9-4c12-9c98-724008a09c21</ebxml:MessageId>
</ebxml:MessageInfo>
<ebxml:PartyInfo>
<ebxml:From>
<ebxml:PartyId type="identifier">Trading Partner X</ebxml:PartyId>
<ebxml:Role>Provider</ebxml:Role>
</ebxml:From>
<ebxml:To>
<ebxml:PartyId type="identifier">XXXXXXX</ebxml:PartyId>
<ebxml:Role>Requestor</ebxml:Role>
</ebxml:To>
</ebxml:PartyInfo>
<ebxml:CollaborationInfo>
<ebxml:AgreementRef>urn:XXXXXXXXX</ebxml:AgreementRef>
<ebxml:Service type="Web Service">urn:XXXXXXXX</ebxml:Service>
<ebxml:Action>customerInformation</ebxml:Action>
<ebxml:ConversationId>e302426a-b2d9-4ff1-a14b-fbbc2f40a017</ebxml:ConversationId>
</ebxml:CollaborationInfo>
</ebxml:UserMessage>
</ebxml:Messaging>
</soapenv:Header>
<soapenv:Body>
<urn:ConnectionTest>
<Message>Bonjour</Message>
</urn:ConnectionTest>
</soapenv:Body>
</soapenv:Envelope>
我们得到了一些文件。安全部分复制如下
必须按以下顺序将以下安全性应用于每个请求: wsse:UsernameToken 必须包含并包含:
- wsse:Username 元素值的代理的门户用户名
密码元素中 wsse:PasswordText(明文)值的代理门户密码 签名块:使用 x509 证书创建数字签名。每个软件提供者都需要持有和保护[待定]颁发的有效证书和私钥。对于每个服务请求,软件必须:
包括与用于签名的私钥匹配的证书作为 wsse:BinarySecurityToken 并将其用作签名的 wsse:SecurityTokenReference
- 签署 wsse:BinarySecurityToken
- 签署 wsse:UsernameToken
- 使用规范化方法算法:http ://www.w3.org/2001/10/xml-exc-c14n#
- 使用签名方法算法:http ://www.w3.org/2000/09/xmldsig#rsa-sha1
- 使用摘要法算法:http ://www.w3.org/2000/09/xmldsig#sha1