我有一个PHP脚本,在SAML身份验证过程中充当IdP。 PHP脚本生成SAML响应,该响应发送给我们的供应商(service.com)。但是,我一直收到“ID6018:摘要验证失败以供参考”错误消息。
对于证书,我使用的是通过openssl生成的2048位自签名RSA证书。供应商在其SP上加载了相同的证书及其公钥。
这是生成并签署SAML响应的PHP代码:
$response_params = array();
$time = time();
$response_params['IssueInstant'] = samlGetDateTime(time());
$response_params['NotOnOrAfter'] = $notOnOrAfter;
$response_params['NotBefore'] = $notBefore;
$response_params['AuthnInstant'] = samlGetDateTime(time());
$response_params['SessionNotOnOrAfter'] = samlGetDateTime(time());
$response_params['ID'] = samlCreateId();
$response_params['assertID'] = samlCreateId();
$response_params['issuer'] = $issuer;
$response_params['email'] = $authenticatedUser;
$response_params['x509'] = <<<X509
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
X509;
$private_key = <<<RSA_PRIVATE_KEY
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
RSA_PRIVATE_KEY;
$xml = new DOMDocument('1.0','utf-8');
$resp = $xml->createElementNS('urn:oasis:names:tc:SAML:2.0:protocol', 'samlp:Response');
$resp->setAttribute('xmlns:saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
$resp->setAttribute('ID',$response_params['ID']);
$resp->setAttribute('Version','2.0');
$resp->setAttribute('IssueInstant',$response_params['IssueInstant']);
$resp->setAttribute('Destination',$destination);
$resp->setAttribute('InResponseTo',$requestID);
$xml->appendChild($resp);
$issuer = $xml->createElementNS('urn:oasis:names:tc:SAML:2.0:assertion','samlp:Issuer',$response_params['issuer']);
$resp->appendChild($issuer);
$status = $xml->createElementNS('urn:oasis:names:tc:SAML:2.0:protocol','samlp:Status');
$resp->appendChild($status);
$statusCode = $xml->createElementNS('urn:oasis:names:tc:SAML:2.0:protocol','samlp:StatusCode');
$statusCode->setAttribute('Value', 'urn:oasis:names:tc:SAML:2.0:status:Success');
$status->appendChild($statusCode);
$assertion = $xml->createElementNS('urn:oasis:names:tc:SAML:2.0:assertion','saml:Assertion');
$assertion->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
$assertion->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$assertion->setAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
$assertion->setAttribute('ID',$response_params['assertID']);
$assertion->setAttribute('Version','2.0');
$assertion->setAttribute('IssueInstant',$response_params['IssueInstant']);
$resp->appendChild($assertion);
$assertion->appendChild($xml->createElement('saml:Issuer',$response_params['issuer']));
$subject = $xml->createElement('saml:Subject');
$assertion->appendChild($subject);
$nameid = $xml->createElement('saml:NameID',$response_params['email']);
$nameid->setAttribute('Format','urn:oasis:names:tc:SAML:2.0:nameid-format:email');
$nameid->setAttribute('SPNameQualifier','https://service.com/adfs/ls/');
$subject->appendChild($nameid);
$confirmation = $xml->createElement('saml:SubjectConfirmation');
$confirmation->setAttribute('Method','urn:oasis:names:tc:SAML:2.0:cm:bearer');
$subject->appendChild($confirmation);
$confirmationdata = $xml->createElement('saml:SubjectConfirmationData');
$confirmationdata->setAttribute('InResponseTo',$requestID);
$confirmationdata->setAttribute('NotOnOrAfter',$response_params['NotOnOrAfter']);
$confirmationdata->setAttribute('Recipient',$destination);
$confirmation->appendChild($confirmationdata);
$condition = $xml->createElement('saml:Conditions');
$condition->setAttribute('NotBefore',$response_params['NotBefore']);
$condition->setAttribute('NotOnOrAfter',$response_params['NotOnOrAfter']);
$assertion->appendChild($condition);
$audiencer = $xml->createElement('saml:AudienceRestriction');
$condition->appendChild($audiencer);
$audience = $xml->createElement('saml:Audience','http://service.com/adfs/services/trust');
$audiencer->appendChild($audience);
$authnstat = $xml->createElement('saml:AuthnStatement');
$authnstat->setAttribute('AuthnInstant',$response_params['AuthnInstant']);
$authnstat->setAttribute('SessionIndex','_'.samlCreateId());//$response_params['assertID']
$authnstat->setAttribute('SessionNotOnOrAfter',$response_params['SessionNotOnOrAfter']);
$assertion->appendChild($authnstat);
$authncontext = $xml->createElement('saml:AuthnContext');
$authnstat->appendChild($authncontext);
$authncontext_ref = $xml->createElement('saml:AuthnContextClassRef','urn:oasis:names:tc:SAML:2.0:ac:classes:Password');
$authncontext->appendChild($authncontext_ref);
$attrStatement = $xml->createElement('saml:AttributeStatement');
$attr = $xml->createElement('saml:Attribute');
$attr->setAttribute('Name', 'mail');
$attr->setAttribute('NameFormat', 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic');
$attrValue = $xml->createElement('saml:AttributeValue', $response_params['email']);
$attrValue->setAttribute('xsi:type', 'xs:string');
$attr->appendChild($attrValue);
$attrStatement->appendChild($attr);
$attr = $xml->createElement('saml:Attribute');
$attr->setAttribute('Name', 'preferredLanguage');
$attr->setAttribute('NameFormat', 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic');
$attrValue = $xml->createElement('saml:AttributeValue', 'en');
$attrValue->setAttribute('xsi:type', 'xs:string');
$attr->appendChild($attrValue);
$attrStatement->appendChild($attr);
$assertion->appendChild($attrStatement);
//Private KEY
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private'));
$objKey->loadKey($private_key);
//Sign the Assertion
$objXMLSecDSig = new XMLSecurityDSig();
$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objXMLSecDSig->addReferenceList(array($assertion), XMLSecurityDSig::SHA1,
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),array('id_name'=>'ID'));
$objXMLSecDSig->sign($objKey);
$objXMLSecDSig->add509Cert($response_params['x509']);
$objXMLSecDSig->insertSignature($assertion,$subject);
$r = $xml->saveXML();
return $r;
这是创建的SAML响应:
<?xml version="1.0" encoding="utf-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="hlboelmomjlpigfakcaaenjnkfdeldibobmfddaa" Version="2.0" IssueInstant="2016-04-27T18:20:17Z" Destination="https://service.com/adfs/ls/" InResponseTo="id-694bef3c-da75-402a-9275-0f6170ace280">
<samlp:Issuer xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">PHP_URL</samlp:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="pfx3116ddd8-61a9-5c07-70ba-abc1781ebc0d" Version="2.0" IssueInstant="2016-04-27T18:20:17Z">
<saml:Issuer>PHP_URL</saml:Issuer>
<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:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#pfx3116ddd8-61a9-5c07-70ba-abc1781ebc0d">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>m89OYak6/qfoES3ncu1bgXkef9Q=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>PXkGpH8aKgGf+iQpqN57OJvtS3+m0EsHcY+J8H6mC8S/KfHQzwtHXsLK4Pz6ykH0HTX0gsM3js24NqOciylrSvuBEo8QjA8Jk5prNnU5Xbv5u0oyjCQmx5eeBhwgsJ4DolTuM2kHskYcUtcDEdcQLmj6CsgfWmn3D4tf1t6T0LzZVFy3RnAcdUFhC/BAHI1a20ddTjoygJYCuxh8MdwQ6uAmpIGKSVHrRB1FJas4mz277+jz2JleUq8fYGfjZNVrAkWX7+OW+vFwEfW+FcthHU0kslifnLEeY749O4oOPBsOD+f+vB7dfOXztztCB/SAeTVhntb5AktbLBBnvxHiXQ==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>CERTIFICATE</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:email" SPNameQualifier="https://service.com/adfs/ls/">myemail@domain.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="id-694bef3c-da75-402a-9275-0f6170ace280" NotOnOrAfter="2016-04-27T18:30:17Z" Recipient="https://service.com/adfs/ls/"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2016-04-27T18:10:17Z" NotOnOrAfter="2016-04-27T18:30:17Z">
<saml:AudienceRestriction>
<saml:Audience>http://service.com/adfs/services/trust</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2016-04-27T18:20:17Z" SessionIndex="_blfhnlolcoogjokbahplfacoehddoglankhaedgg" SessionNotOnOrAfter="2016-04-27T18:20:17Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">myemail@domain.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="preferredLanguage" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">en</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
非常感谢任何帮助!