【问题标题】:Reference for URI has no XMLSignatureInput using Apache SantuarioURI 的参考没有使用 Apache Santuario 的 XMLSignatureInput
【发布时间】:2014-05-02 07:05:36
【问题描述】:

我需要将我的 Web 应用程序与 SSO 集成。我收到带有数字签名的 SAML 响应。有人告诉我,第一步是使用标准 XML 签名验证技术确保签名与 SAML 的内容匹配。

我正在使用 Apache Santuario,因为标准 Java XML API 不适用于 JBOSS 7。 https://issues.jboss.org/browse/AS7-4248

错误:

org.apache.xml.security.signature.MissingResourceFailureException: The Reference for URI #973348f8-3980-4403-bede-df6d3f2a0f10 has no XMLSignatureInput
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID 973348f8-3980-4403-bede-df6d3f2a0f10
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID 973348f8-3980-4403-bede-df6d3f2a0f10
Original Exception was org.apache.xml.security.signature.ReferenceNotInitializedException: Cannot resolve element with ID 973348f8-3980-4403-bede-df6d3f2a0f10
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID 973348f8-3980-4403-bede-df6d3f2a0f10
  at org.apache.xml.security.signature.Manifest.verifyReferences(Manifest.java:414)
  at org.apache.xml.security.signature.SignedInfo.verify(SignedInfo.java:259)
  at org.apache.xml.security.signature.XMLSignature.checkSignatureValue(XMLSignature.java:724)
  at org.apache.xml.security.signature.XMLSignature.checkSignatureValue(XMLSignature.java:656)

我能找到的唯一帮助是使用 setIdAttributeNS() 将 Assertion 元素 ID 设置为 null。我不知道如何或何时这样做。我觉得我现在可能会破坏 SAML。 http://comments.gmane.org/gmane.text.xml.security.devel/7609

XML sn-p:

<samlp:Response xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="http://www.carrier.com" ID="da55c478-f2f6-43b7-ba2f-a130d60abbf8" IssueInstant="2013-05-31T21:33:21Z" Version="2.0">
  <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://someissuer.com/SAML2/SSO</saml:Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success">
    </samlp:StatusCode>
  </samlp:Status>
  <saml:Assertion ID="973348f8-3980-4403-bede-df6d3f2a0f10" IssueInstant="2013-05-31T21:33:21Z" Version="2.0">
    <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://someissuer.com/SAML2/SSO</saml:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
        <Reference URI="#973348f8-3980-4403-bede-df6d3f2a0f10">
          <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          </Transforms>
          <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
          <DigestValue>DIGEST VALUE</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">BIG STRING</SignatureValue>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
          <X509Certificate>ANOTHER BIG STRING</X509Certificate>
        </X509Data>
      </KeyInfo>
    </ds:Signature>

代码:

// load XML from string
InputSource inputSource = new InputSource( new StringReader(saml) );

DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setNamespaceAware(true);
Document doc = f.newDocumentBuilder().parse(inputSource);

// new xpath
xpath = XPathFactory.newInstance().newXPath();

NodeList signatureNodes = doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
if (signatureNodes.getLength() == 0) {
    throw new Exception("Signature NOT found!");
}

Element sigElement = (Element) signatureNodes.item(0);
if (sigElement == null) {
    throw new Exception("Signature element is null!");
    }

    XMLSignature signature = new XMLSignature(sigElement, "");

// key
KeyInfo ki = signature.getKeyInfo();
if (ki == null) {
    throw new Exception("Did not find KeyInfo");
}

// validate 
X509Certificate cert = signature.getKeyInfo().getX509Certificate();
if (cert == null) {
    PublicKey pk = signature.getKeyInfo().getPublicKey();
    if (pk == null) {
        throw new Exception("Did not find Certificate or Public Key");
    }

    valid = signature.checkSignatureValue(pk);
}

else {
    valid = signature.checkSignatureValue(cert);
}

【问题讨论】:

    标签: java xml apache jboss


    【解决方案1】:

    修好了!我非常接近,这就是我所做的。

    我必须先获取 Assertion 元素并注册 ID。

    // load XML from string
    InputSource inputSource = new InputSource( new StringReader(saml) );
    
    // load document
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    docFactory.setNamespaceAware(true);
    document = docFactory.newDocumentBuilder().parse(inputSource);
    
    // create xpath with appropriate namespace context
    xpath = XPathFactory.newInstance().newXPath();
    xpath.setNamespaceContext(new SAMLNamespaceContext());
    
    // load assertion to get signed ID
    NodeList assertionNodes = (NodeList) xpath.evaluate("samlp:Response/saml:Assertion", document, XPathConstants.NODESET);
    if (assertionNodes.getLength() == 0) {
        throw new Exception("Cannot find Assertion element");
    } 
    
    // register ID
    Element assertionElement = (Element) assertionNodes.item(0);
    assertionElement.setIdAttributeNS(null, "ID", true);
    
    // load signature
    NodeList signatureNodes = document.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
    if (signatureNodes.getLength() == 0)
        throw new Exception("Signature NOT found!");
    
    Element sigElement = (Element) signatureNodes.item(0);
    if (sigElement == null) 
        throw new Exception("Signature element is null!");
    
    XMLSignature signature = new XMLSignature(sigElement, "");
    
    // check for key
    KeyInfo ki = signature.getKeyInfo();
    if (ki == null) {
        throw new Exception("Did not find KeyInfo");
    }
    
    // get cert and validate 
    X509Certificate cert = signature.getKeyInfo().getX509Certificate();
    if (cert == null) {
        PublicKey pk = signature.getKeyInfo().getPublicKey();
        if (pk == null) {
            throw new Exception("Did not find Certificate or Public Key");
        }
    
        valid = signature.checkSignatureValue(pk);
    }
    else {
        valid = signature.checkSignatureValue(cert);
    }
    

    【讨论】:

    • “注册 ID”到底是什么意思?
    • “注册ID”表示注册属性,当尝试解析与“#”样式的URI相关的节点时,必须将其值视为标识符
    猜你喜欢
    • 2011-07-02
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多