使用C#编程方式将wsse:Security和BinarySecurityToken添加到信封xml文件中,而无需Web引用

4

目前我需要生成一个XML文件来模拟SOAP请求,这个文件需要用X.509证书进行签名。

现在我有这个方法来对文件进行签名:

public static void SignXml(XmlDocument xmlDoc, X509Certificate2 uidCert)
{
    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

    // Check arguments. 
    if (xmlDoc == null)
        throw new ArgumentException("xmlDoc");
    if (rsaKey == null)
        throw new ArgumentException("Key");

    // Create a SignedXml object.
    SignedXml signedXml = new SignedXml(xmlDoc);

    // Add the key to the SignedXml document.
    signedXml.SigningKey = rsaKey;

    // Specify a canonicalization method.
    signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

    // Set the InclusiveNamespacesPrefixList property.        
    XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
    canMethod.InclusiveNamespacesPrefixList = "sol soapenv";

    // Create a reference to be signed.
    Reference reference = new Reference();
    Reference reference1 = new Reference();
    reference.Uri = "";            
    reference1.Uri = "";

    string referenceDigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
    reference.DigestMethod = referenceDigestMethod;
    reference1.DigestMethod = referenceDigestMethod;

    // Add an enveloped transformation to the reference.
    //XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    //reference.AddTransform(env);

    XmlDsigExcC14NTransform c14n = new XmlDsigExcC14NTransform();
    c14n.InclusiveNamespacesPrefixList = "wsse sol soapenv";

    reference.AddTransform(c14n);

    XmlDsigExcC14NTransform c14n1 = new XmlDsigExcC14NTransform();
    c14n1.InclusiveNamespacesPrefixList = "sol";
    reference1.AddTransform(c14n1);

    // Add the reference to the SignedXml object.
    signedXml.AddReference(reference);
    signedXml.AddReference(reference1);

    // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
    KeyInfo keyInfo = new KeyInfo();

    SecurityTokenReference skr = new SecurityTokenReference();
    skr.Reference = "some";
    skr.ValueType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";

    keyInfo.AddClause(skr);
    signedXml.KeyInfo = keyInfo;

    // Compute the signature.
    signedXml.ComputeSignature();

    // Get the XML representation of the signature and save 
    // it to an XmlElement object.
    XmlElement xmlDigitalSignature = signedXml.GetXml();

    System.Console.WriteLine(signedXml.GetXml().InnerXml);

    // Append the element to the XML docu0ment.
    //xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    XmlElement root = (XmlElement)xmlDoc.GetElementsByTagName("soapenv:Envelope")[0];
    string query = string.Format("//*[@Id='{0}']", "IDH"); //Search the Header tag to add signature
    XmlElement myElement = (XmlElement)xmlDoc.DocumentElement.SelectSingleNode(query);
    myElement.AppendChild(xmlDigitalSignature);
}

我可以生成这个文件。
<soapenv:Envelope xmlns:sol="
http://www.sol.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header Id="IDH">
        <sol:authentication>
            <id>4942014103</id>
            <userid>ME.8494</userid>
        </sol:authentication>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
                <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                    <InclusiveNamespaces PrefixList="sol soapenv" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </CanonicalizationMethod>
                <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <Reference URI="">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                            <InclusiveNamespaces PrefixList="wsse sol soapenv" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                        </Transform>
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                    <DigestValue>BEZBfqQ1QGgbhxvtB83/tr2Yt/8uJPEfvrh8Tn5O6oQ=</DigestValue>
                </Reference>
                <Reference URI="">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                            <InclusiveNamespaces PrefixList="sol" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                        </Transform>
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                    <DigestValue>BEZBfqQ1QGgbhxvtB83/tr2Yt/8uJPEfvrh8Tn5O6oQ=</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>MiOL7D2YfIModsGXh+mm+Ok+oApaYMNenX8xFgwMCXcxW7blHqAPJ2VKGhraAdqy9crAvzEgT6MqD/T9ZWPnK1IHOcQlCt5XICkAlJVnLB78rWkYaTsjNLak2KSvQVCqEDIp0GEwGE6S+5cJykWmbOGiZg50VFFN8QRUlYiIB8I=</SignatureValue>
            <KeyInfo>
                <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                    <wsse:Reference URI="#some" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
                </wsse:SecurityTokenReference>
            </KeyInfo>
        </Signature>
    </soapenv:Header>
    <soapenv:Body>
        <sol:solbus>
            <in>H4sIAAAAAAAEAI1VXW+bMBR9n7T/YPFcvgJJW9RQUZJ0aAnpAp26vVQWOK2lgCPjJM2/nwEHTEKk8cY59/heHx/Dw+NXtgF7RAtM8rFiaoby6H7/9rBmiTPzYt97X079CeBFeeFWF8FXisfDK2dXT9cDhoB0sj9EMfGIapvy3mUfKJMqjivGAwT5AiVMUajpUdzR2CktRhGHGIrdeQJZAdt/xtbyryBOZJyGc4F1aqUsBnBKCacoGKAn6gaIuSCuQw7+hEKE9x/uGTbAvzYxC684n39+VZuy8fLZpr9p39oPdWSqvEFOZFhhmrCnY5o0d38Vbr+jhJukIJwnuJe41q3QUhicRmYu6LW9lfS2S4FDeaGm/nuWxdY5fOdQ19pmS37e7AS5LSqrrkfCRB/iCbFFGJFHS5jT1Od3DT4ZqwFfIptGku+g+njRq/UoY9Uu9HqjUc3Yk4NfesUxvCDL1/GYblvf/aoYKc1YiqGaYFK0vdhbcKPDCZzsFq6QfLeu2W7lXPoWDjZeR7oRA16NlU+n+MdSXNEtnn3HXbepJtgRdv9RN4v6fh6xR4/CVeTMMYmDdg4oVPr6sN34MjNGSdaVxPvryl/nHFITD+KYYbzNqPloz1SJ4wZZ9BviZA7+ZKvxqsmroWSTmvT3BT/k9AsqO0dGusLN5CRerUWaoT/bN71F6Ymjh9q6S36nngMxEmBLFwcAAA==</in>
        </sol:solbus>
    </soapenv:Body>
</soapenv:Envelope>

在方法SingXml中,xmlDoc包含此xml,唱完后我会添加到头部。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sol="http://www.sol.com">
  <soapenv:Header Id="IDH">
    <sol:authentication>
      <id></id><userid></userid> <------ With info
    </sol:authentication>
  </soapenv:Header>
  <soapenv:Body>
    <sol:siatbus>
      <in></in> <-----With info
    </sol:siatbus>
  </soapenv:Body>
</soapenv:Envelope>

我需要更多的东西,签名必须在Header标签内部的Security标签中,并带有BinarySecurityToken元素。
例如:
<soapenv:Header> <!-- extrac of the example file -->
  <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-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="X509-D53CCD6983E4CE0BD7142791021078262">
        MIIDbDgg4iF74cqiF6NcnzBnD9qA2MB6hSo38e0RISilEFSzWikDqBtOjgm7ux9fdeHojDm4uvhsSfbEyGmGTAQRzg9yIiD3ovjOzuZsf+I3HWS9F6xl6sb2+wvYXD4DFk/OD+N7UszGsoWFZg
    </wsse:BinarySecurityToken>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          .....
    </ds:Signature>

我可以通过硬编码字符串添加<wsse:Security标签,但我不知道它是否影响了内部的BinarySecurityToken。
令牌中的内部数据(MIIDbDgg4i....)是如何生成的?
我该怎么做才能添加Security标签?
额外信息:
我该如何为Signature及其子元素添加前缀ds

2
你已经找到解决方案了吗? - Habeeb
1
为签名及其子元素添加“ds”前缀:您可以为所有“xmlDigitalSignature.ChildNodes”添加一个“foreach”循环,并在其中写入“childNode.Prefix ="ds"”,这将为所有子节点分配前缀。 - randomstudious
1个回答

12

BinarySecurityToken 是证书的base64编码版本。如果您导出证书并复制到文件中,请确保单击了Base-64编码选项,您将看到在 BinarySecurityToken 元素中使用的值。您可以通过在记事本中打开导出的文件来查看此内容。

要通过编程方式直接从客户端证书填充xml元素,请执行以下操作:

var cert = new X509Certificate2(ClientCertificateFilePath, ClientCertificatePassword);
        var export = cert.Export(X509ContentType.Cert, ClientCertificatePassword);
        var base64 = Convert.ToBase64String(export);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接