-1

我有 XML 文档:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
        <saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Version="2.0"
                                IssueInstant="2020-06-01T10:25:15+02:00">
            <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">TEST</saml2:Issuer>
            <saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfHTFVHTDBTVHdBwwTW+ehcM19zsk=</saml2p:Artifact>
        </saml2p:ArtifactResolve>
    </soapenv:Body>
</soapenv:Envelope>

我尝试这样做:

$results = array();
$filename = 'cert.p12';
$password = 'certpass';
$priv_key = openssl_pkcs12_read(file_get_contents($filename), $results, $password);

$doc = new DOMDocument();
$doc->loadXML($xml);
$xp = new DOMXPath($doc);
$xp->registerNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
$xp->registerNamespace('saml2p','urn:oasis:names:tc:SAML:2.0:protocol');
$xp->registerNamespace('saml2','urn:oasis:names:tc:SAML:2.0:assertion');
$xp->registerNamespace('ds',XMLSecurityDSig::XMLDSIGNS);

$artifactResolveNode = $xp->query('/*[local-name()=\'Envelope\']/*[local-name()=\'Body\']/*[local-name()=\'ArtifactResolve\']')->item(0);

if($artifactResolveNode){

    $objDSig = new XMLSecurityDSig();
    $objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
    $objDSig->addReference(
        $artifactResolveNode,
        XMLSecurityDSig::SHA256,
        array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#'),
        array('force_uri' => true)
    );
    $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
    $objKey->loadKey($results['pkey'], FALSE);
    $objDSig->sign($objKey);
    $objDSig->add509Cert($results['cert']);
    $objDSig->appendSignature($doc->documentElement());
    echo $doc->saveXML();
}

在错误位置使用 Singnature 的输出是:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
    <saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Version="2.0" IssueInstant="2020-06-01T10:25:15+02:00" Id="pfx97783ab1-0339-0f2e-b759-9e9c07e347b0">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">TEST</saml2:Issuer><saml2p:Artifact>AAQAAKFbFR94fxqmioAqjJUwfyUtjJbv0uEPB7ooopodBwwTW+ehcM19zsk=</saml2p:Artifact></saml2p:ArtifactResolve>
    </soapenv:Body>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

  <ds:SignedInfo>
(...)
</soapenv:Envelope>

我想将签名节点放在 ISSUER 和 ARTIFACT 之间。这个位置对于正确发送 SOAP Envelope 非常重要。有可能的?

4

1 回答 1

0

我发现!我需要在下面添加代码:

$artifactNode = $xp->query('/*[local-name()=\'Envelope\']/*[local-name()=\'Body\']/*[local-name()=\'ArtifactResolve\']/*[local-name()=\'Artifact\']')->item(0);

并像这样附加签名:

    $objDSig->insertSignature($artifactResolveNode,$artifactNode);
于 2020-06-02T07:42:48.073 回答