javascript - 使用 JavaScript 和 jQuery 修改命名空间 XML

标签 javascript jquery xml xml-namespaces

我有一个命名空间 XML 文档,必须使用特殊的浏览器插件对其进行签名。

这是和平代码,签署文件:

    var oCertificate = GetCertificateBySubjectName(certificateName);

    var token = oCertificate.Export(CADESCOM_ENCODE_BASE64);

    var element, xmlDoc;

    xmlDoc = $.parseXML(doc.toString());
    element = $(xmlDoc).find("o\\:BinarySecurityToken");
    element.text(token);

    var xmlString = undefined;

    if (window.ActiveXObject) {
        xmlString = xmlDoc[0];
    }

    if (xmlString === undefined) {
        var oSerializer = new XMLSerializer();
        xmlString = (new XMLSerializer()).serializeToString(xmlDoc);
    }

    var doc = SignCreate(oCertificate, xmlString);

其中 doc 是包含 XML 的字符串。

以下是必须签署的 XML 协议(protocol):

<s:Header>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:actor="http://smev.gosuslugi.ru/actors/smev">
        <o:BinarySecurityToken u:Id="uuid-ee82d445-758b-42cb-996c-666b74b60022-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"/>
        <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/2001/04/xmldsig-more#gostr34102001-gostr3411" />
                <Reference URI="#_1">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411" />
                    <DigestValue/>
                </Reference>
            </SignedInfo>
            <SignatureValue/>
            <KeyInfo>
                <o:SecurityTokenReference>
                    <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-ee82d445-758b-42cb-996c-666b74b60022-2" />
                </o:SecurityTokenReference>
            </KeyInfo>
        </Signature>
    </o:Security>
</s:Header>

文件的签署工作如下。使用 xmlDoc = $.parseXML(message.toString()); element = $(xmlDoc).find("o\\:BinarySecurityToken"); element.text(token); 我将证书中的 token 放入 <o:BinarySecurityToken>然后将其转换回字符串并发送到签名。

在此步骤中,我得到了:

<o:BinarySecurityToken u:Id="uuid-ee82d445-758b-42cb-996c-666b74b60022-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">!!TOKEN!!</o:BinarySecurityToken>

然后

<o:BinarySecurityToken u:Id="uuid-ee82d445-758b-42cb-996c-666b74b60022-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">!!!TOKEN!!!</o: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/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
                <Reference URI="#_1">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
                    <DigestValue>!!!SIGNATURE DIGEST VALUE!!!</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>!!!SIGNATURE!!!</SignatureValue>

在 FireFox 和 (!)IE 中一切都运行良好,但在 Google Chrome 中却不起作用。在 Chrome 代码中,将 token 保留为空,所有其他方法都将不起作用。

所以,我的问题是:我应该怎么做才能解决这个问题?我尝试使用https://github.com/rfk/jquery-xmlns给 jQuery 一些处理命名空间 XML 的能力,但是这个库没有在我的代码中运行。

提前致谢。

附注我使用 jQuery 1.10.2

最佳答案

jQuery 不支持命名空间,仅支持节点名称中的冒号。我无法让 jquery-xmlns 插件与当前的 jQuery 版本一起使用。

新的 Document.querySelector()Document.querySelectorAll() 方法也不支持命名空间。

但是 Document.evaluate()Document 本身确实如此。他们允许使用 XPath。除 IE 之外的所有现代浏览器都支持 Document.evaluate()。对于 IE JavaScript library可用于将方法添加到文档对象。

var dom = (new DOMParser()).parseFromString(xml, 'application/xml');

var resolver = {
  namespaces : {
   'o' : 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
  },
  lookupNamespaceURI : function(prefix) {
    if (prefix == '') {
      return null;
    }   
    return this.namespaces[prefix] || null;
  }
};

var node = dom.evaluate(
  '//o:BinarySecurityToken',  
  dom,
  resolver,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null 
).singleNodeValue;
node.appendChild(dom.createTextNode('TOKEN_TEXT')); 

document.querySelector('#output').textContent = (new XMLSerializer()).serializeToString(dom);

演示:http://jsfiddle.net/mec2qxLa/2/

要使其与 IE 兼容,您需要加载 xpath.js。它将评估方法附加到 document 对象。对于新的 Document 实例,您可以从那里获取它。它不发布 XPathResult 对象,但定义了提供该对象的 xpath 对象。

var dom = (new DOMParser()).parseFromString(xml, 'application/xml');
if (!dom.evaluate && document.evaluate) {
  dom.evaluate = document.evaluate;
  if (typeof XPathResult == 'undefined') {
    XPathResult = xpath.XPathResult;
  }
}
...

关于javascript - 使用 JavaScript 和 jQuery 修改命名空间 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28189869/

相关文章:

javascript - 多个 Javascript 并行运行

python - 用python解析xml中的CDATA

javascript - AngularJS路由到具有不同 Controller 的不同页面

javascript - 在 Rails 中渲染通过 Pusher 传递的对象

javascript - jQuery 多选下拉菜单,带有所选项目的关闭按钮

javascript - 如何在不使用任何其他鼠标事件的情况下检测长按鼠标事件

xml - XSL if 测试在有值时显示内容

Java 对 PMML 的支持

javascript - 当文本由外部源更新时,防止 ckeditor 触发设置回调

javascript - lodash 按数组 Angular 5 过滤对象数组