目前我在.NET中实现一个客户端来使用用JAVA编写的SOAP服务(我不确定)。 SOAP信封必须以非常具体的方式签名,这是一个噩梦,试图这样做。
这是他们期望的信封的一个例子:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#id-319644606">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>uQpjnTTrxxI7ck9FpeEI6YRVHBA=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
paNzJWyYDBNTj8Ay4z0/wOKKQUCe/z0q/LRcDgB9CP1fn/FZW8uyLdASHxs2HHlpYG7daFvbtpsQ
ZoiIUSzUuUBUAjjaqLWRZyUeCqc48f8X6vxR52mLARnJdPC9MWPZg8FTsoqJ2nvyH28chqf8Svql
KxgtCtBiL9wPnkzG5m4=
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-1827725498">
<wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-131635550">
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=DESARROLLO,OU=INGENIERIA,O=ASOBANCARIA,L=BOGOTA,ST=D.C,C=CO</ds:X509IssuerName>
<ds:X509SerialNumber>1141316577</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2014-10-29T22:14:01Z</wsu:Created>
<wsu:Expires>2014-10-29T22:19:01Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-319644606">
<ns1:evaluarCuestionario xmlns:ns1="http://ws.confrontaultra.cifin.asobancaria.com" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<p_parametrosSeguridad href="#id0"></p_parametrosSeguridad>
<p_respuestaCuestionario href="#id1"></p_respuestaCuestionario>
</ns1:evaluarCuestionario>
<multiRef xmlns:ns2="http://ultras.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:RespuestaCuestionarioULTRADTO">
<secuenciaCuestionario href="#id2"></secuenciaCuestionario>
<codigoCuestionario href="#id3"></codigoCuestionario>
<respuestas xmlns:ns3="http://ultra.dto.confrontaultra.cifin.co" soapenc:arrayType="ns3:RespuestaPreguntaULTRADTO[5]" xsi:type="soapenc:Array">
<respuestas href="#id4"></respuestas>
<respuestas href="#id5"></respuestas>
<respuestas href="#id6"></respuestas>
<respuestas href="#id7"></respuestas>
<respuestas href="#id8"></respuestas>
</respuestas>
</multiRef>
<multiRef xmlns:ns4="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:ParametrosSeguridadULTRADTO">
<claveCIFIN xsi:type="soapenc:string">90681</claveCIFIN>
<password xsi:type="soapenc:string">H32std</password>
</multiRef>
<multiRef xmlns:ns5="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id7" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:RespuestaPreguntaULTRADTO">
<secuenciaPregunta href="#id9"></secuenciaPregunta>
<secuenciaRespuesta href="#id10"></secuenciaRespuesta>
</multiRef>
<multiRef xmlns:ns6="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id4" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns6:RespuestaPreguntaULTRADTO">
<secuenciaPregunta href="#id11"></secuenciaPregunta>
<secuenciaRespuesta href="#id12"></secuenciaRespuesta>
</multiRef>
<multiRef xmlns:ns7="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id6" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns7:RespuestaPreguntaULTRADTO">
<secuenciaPregunta href="#id13"></secuenciaPregunta>
<secuenciaRespuesta href="#id14"></secuenciaRespuesta>
</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long">8846263</multiRef>
<multiRef xmlns:ns8="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id5" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns8:RespuestaPreguntaULTRADTO">
<secuenciaPregunta href="#id15"></secuenciaPregunta>
<secuenciaRespuesta href="#id16"></secuenciaRespuesta>
</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id3" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">7062</multiRef>
<multiRef xmlns:ns9="http://ultra.dto.confrontaultra.cifin.co" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id8" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns9:RespuestaPreguntaULTRADTO">
<secuenciaPregunta href="#id17"></secuenciaPregunta>
<secuenciaRespuesta href="#id18"></secuenciaRespuesta>
</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id12" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">150136315</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id14" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">150136266</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id17" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">7</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id10" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">150136259</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id16" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">150136277</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id9" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">20</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id18" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">150136247</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id15" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">35</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id13" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">9</multiRef>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id11" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int">92</multiRef>
</soapenv:Body>
</soapenv:Envelope>
基本上我有两个问题:
另外,请注意KeyInfo标记内的wsse:SecutiryTokenReference标记。 SignedXml类默认在KeyInfo元素中生成此xml:
<KeyInfo>
<X509Data>
<X509IssuerSerial>
<X509IssuerName>CN=RootCATest</X509IssuerName>
<X509SerialNumber>228801528337358580231830876343013017805</X509SerialNumber>
</X509IssuerSerial>
</X509Data>
</KeyInfo>
那么,如何将此<X509Data>
元素替换为<wsse:SecurityTokenReference>
元素。
到目前为止,为了签署xml文档,我发现了很多帖子和博客后的实现。这是我的实施:
public class Signer
{
public XmlDocument SignMessage(XmlDocument xmlDoc, X509Certificate2 certificate)
{
var ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
var body = xmlDoc.DocumentElement.SelectSingleNode(@"//soapenv:Body", ns) as XmlElement;
if (body == null)
throw new ApplicationException("No body tag found");
body.SetAttribute("id", "Body");
var signedXml = new SignedXml(xmlDoc);
var keyInfo = new KeyInfo();
signedXml.SigningKey = certificate.PrivateKey;
var keyInfoData = new KeyInfoX509Data();
keyInfoData.AddIssuerSerial(certificate.Issuer, certificate.GetSerialNumberString());
keyInfo.AddClause(keyInfoData);
signedXml.KeyInfo = keyInfo;
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
var reference = new Reference { Uri = "#Body" };
reference.AddTransform(new XmlDsigExcC14NTransform());
signedXml.AddReference(reference);
signedXml.ComputeSignature();
var signedElement = signedXml.GetXml();
var securityNode = xmlDoc.CreateElement(
"wsse",
"Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
securityNode.AppendChild(signedElement);
var timeStampNOde = xmlDoc.CreateElement("Timestamp");
var createdNode = xmlDoc.CreateElement("Created");
createdNode.InnerText = JsonConvert.SerializeObject(DateTime.UtcNow, new IsoDateTimeConverter());
var expiresNode = xmlDoc.CreateElement("Created");
expiresNode.InnerText = JsonConvert.SerializeObject(DateTime.UtcNow.AddMinutes(5), new IsoDateTimeConverter());
timeStampNOde.AppendChild(createdNode);
timeStampNOde.AppendChild(expiresNode);
securityNode.AppendChild(timeStampNOde);
var soapHeader = xmlDoc.DocumentElement.SelectSingleNode(@"//soapenv:Header", ns) as XmlElement;
if (soapHeader == null)
{
soapHeader = xmlDoc.CreateElement("soapenv:Header", "");
xmlDoc.DocumentElement.InsertBefore(soapHeader, xmlDoc.DocumentElement.ChildNodes[0]);
}
soapHeader.AppendChild(securityNode);
return xmlDoc;
}
任何评论,建议,帖子等都会非常有帮助。考虑一下我必须按要求发送信封,因为这个组织不仅仅为我改变它,我猜他们有很多客户。
非常感谢!
答案 0 :(得分:3)
您的方法有效但不使用WCF安全功能。我建议先尝试使用WCF,然后再尝试使用自定义签名。首先尝试使用此WCF绑定:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="MutualCertificate" includeTimestamp="false"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<secureConversationBootstrap />
</security>
<httpTransport />
</binding>
</customBinding>
还要将WCF配置为仅签名:
c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
这将创建一个类似于您需要的SOAP,但keyInfo将作为对binarySecurityToken的引用,而不是像示例中那样。不过,我建议尝试使用它,它很有可能会起作用。
如果失败,您需要创建a code binding并使用x509 params。或者,您可以实现custom WCF encoder来更改密钥引用。
我没有完全遵循你的代码。没有WCF签署自己的方法是有效的,但你很可能会有错误。