Подписание сообщения SOAP с подписью XML и WCF

1

В настоящее время я внедряю клиента в.NET для использования службы SOAP, написанной в JAVA (я не уверен). Конверт 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>

Так что в основном у меня есть 2 проблемы:

  1. Я не смог установить правильные пространства имен в заголовок подписи. (пространство имен ds)
  2. Также обратите внимание на тег wsse: SecutiryTokenReference внутри тега KeyInfo. Класс SignedXml генерирует этот xml по умолчанию внутри элемента KeyInfo:

    <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;
        }

Любые комментарии, предложения, сообщения и т.д. Будут очень полезны. Подумайте, я должен отправить конверт по своему усмотрению, поскольку эта организация не изменит его только для меня, я предполагаю, что у них много клиентов.

Большое спасибо!

Теги:
soap
wcf

1 ответ

2
Лучший ответ

Ваш подход действителен, но он не использует возможности безопасности 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, а не как в примере. Тем не менее, я предлагаю попробовать с ним, есть хороший шанс, что он будет работать.

Если это не удается, вам нужно будет создать привязку кода и сыграть с параметрами x509. В качестве альтернативы вы можете реализовать собственный кодер WCF для изменения ссылки на ключ.

Я не полностью выполнил ваш код. Подход к подписи без WCF действителен, но есть хорошие шансы, что у вас будут ошибки.

  • 0
    ну я наконец дошел до сервиса. Но он отвечает: «WSDoAllReceiver: сертификат, используемый для подписи, не является доверенным». Я предполагаю, что он не принимает элемент KeyInfo, указывающий на двоичный токен. Можно ли как-нибудь настроить это так, как я показал вам в примере? @YaronNaveh
  • 0
    эта ошибка звучит так, как будто вы используете неверный сертификат для подписи. попробуйте сначала обратиться к сервису с помощью soapui, используя тот же сертификат, чтобы убедиться, что проблема действительно в формате, а не в сертификате.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню