Java 无法使用ColdFusion验证SAML断言
我们从一个Identify提供者那里收到一个标准SAML2.0断言,我无法使用internet上唯一的示例ColdFusion 9示例代码来验证它 下面的代码可以在internet上找到,作为如何使用ColdFusion验证SAML的示例。见本页: SAML XML将作为一个表单post发送给我们。我们已经设置了一个页面来检测传入的断言。相关代码如下:Java 无法使用ColdFusion验证SAML断言,java,coldfusion,saml,x509,assertion,Java,Coldfusion,Saml,X509,Assertion,我们从一个Identify提供者那里收到一个标准SAML2.0断言,我无法使用internet上唯一的示例ColdFusion 9示例代码来验证它 下面的代码可以在internet上找到,作为如何使用ColdFusion验证SAML的示例。见本页: SAML XML将作为一个表单post发送给我们。我们已经设置了一个页面来检测传入的断言。相关代码如下: xmlResponse = getHttpRequestData().content.Trim(); docElement = XmlParse
xmlResponse = getHttpRequestData().content.Trim();
docElement = XmlParse(variables.xmlResponse);
Init = CreateObject("Java", "org.apache.xml.security.Init").Init().init();
SignatureConstants = CreateObject("Java", "org.apache.xml.security.utils.Constants");
SignatureSpecNS = SignatureConstants.SignatureSpecNS;
xmlSignatureClass = CreateObject("Java", "org.apache.xml.security.signature.XMLSignature");
xmlSignature = xmlSignatureClass.init(docElement.getElementsByTagNameNS(SignatureSpecNS,"Signature").item(0),"");
keyInfo = xmlSignature.getKeyInfo();
X509CertificateResolverCN = "org.apache.xml.security.keys.keyresolver.implementations.X509CertificateResolver";
keyResolver = CreateObject("Java", X509CertificateResolverCN).init();
keyInfo.registerInternalKeyResolver(keyResolver);
x509cert = keyInfo.getX509Certificate();
isValid = xmlSignature.checkSignatureValue(x509cert);
ColdFusion 9没有内置的库来处理x509验证,因此将两个Java库导入到我们的ColdFusion安装中。这些来自ApacheSantuario项目。它们是:
序列化程序-2.7.1.jar
xmlsec-1.5.3.jar
代码运行正常,但它总是输出NO,签名无效。我确信这一断言应该是正确的
我承认我只是在这里编写代码,因为我对Java不够熟悉,无法真正理解这里发生的事情
我已经尝试了我能想到的一切。有人能提供一些关于检查什么或修改什么以继续故障排除的提示或想法吗
==更新1-添加SAML断言示例==
Salesforce.com的这个示例断言在格式上与我们收到的断言几乎相同。是的,我们的断言中确实包含了一个公钥,就像这里截断的这个一样
<samlp:Response ID="_257f9d9e9fa14962c0803903a6ccad931245264310738" IssueInstant="2009-06-17T18:45:10.738Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
https://www.salesforce.com
</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion ID="_3c39bc0fe7b13769cab2f6f45eba801b1245264310738"
IssueInstant="2009-06-17T18:45:10.738Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
https://www.salesforce.com
</saml:Issuer>
<saml:Signature>
<saml:SignedInfo>
<saml:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<saml:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<saml:Reference URI="#_3c39bc0fe7b13769cab2f6f45eba801b1245264310738">
<saml:Transforms>
<saml:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<saml:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="ds saml xs"/>
</saml:Transform>
</saml:Transforms>
<saml:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<saml:DigestValue>vzR9Hfp8d16576tEDeq/zhpmLoo=
</saml:DigestValue>
</saml:Reference>
</saml:SignedInfo>
<saml:SignatureValue>
AzID5hhJeJlG2llUDvZswNUrlrPtR7S37QYH2W+Un1n8c6kTC
Xr/lihEKPcA2PZt86eBntFBVDWTRlh/W3yUgGOqQBJMFOVbhK
M/CbLHbBUVT5TcxIqvsNvIFdjIGNkf1W0SBqRKZOJ6tzxCcLo
9dXqAyAUkqDpX5+AyltwrdCPNmncUM4dtRPjI05CL1rRaGeyX
3kkqOL8p0vjm0fazU5tCAJLbYuYgU1LivPSahWNcpvRSlCI4e
Pn2oiVDyrcc4et12inPMTc2lGIWWWWJyHOPSiXRSkEAIwQVjf
Qm5cpli44Pv8FCrdGWpEE0yXsPBvDkM9jIzwCYGG2fKaLBag==
</saml:SignatureValue>
<saml:KeyInfo>
<saml:X509Data>
<saml:X509Certificate>
MIIEATCCAumgAwIBAgIBBTANBgkqhkiG9w0BAQ0FADCBgzELM
[Certificate truncated for readability...]
</saml:X509Certificate>
</saml:X509Data>
</saml:KeyInfo>
</saml:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">
saml01@salesforce.com
</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2009-06-17T18:50:10.738Z"
Recipient="https://login.www.salesforce.com"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2009-06-17T18:45:10.738Z"
NotOnOrAfter="2009-06-17T18:50:10.738Z">
<saml:AudienceRestriction>
<saml:Audience>https://saml.salesforce.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="portal_id">
<saml:AttributeValue xsi:type="xs:anyType">060D00000000SHZ
</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="organization_id">
<saml:AttributeValue xsi:type="xs:anyType">00DD0000000F7L5
</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="ssostartpage"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xsi:type="xs:anyType">
http://www.salesforce.com/security/saml/saml20-gen.jsp
</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="logouturl"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue xsi:type="xs:string">
http://www.salesforce.com/security/del_auth/SsoLogoutPage.html
</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
==更新2-使用keytool向java密钥库添加公钥==
使用keytool命令将公钥添加到java密钥库文件cacerts。我可以看到公钥现在已经添加到我们的cacerts文件中,并且证书被标记为可信
我们在一个*.pem文件中收到了他们的公钥,所以我用它将他们的密钥添加到密钥库中。我还尝试将*.pem文件转换为*.der文件并导入该文件。两个都很好。但是,我的代码仍然为isValid返回NO。啊
*.pem文件中的公钥与SAML断言中的公钥完全匹配。既然您提到了ApacheSantuario,下面是该项目的一个示例,涉及验证XML数字签名 该示例使用X509证书中的公钥,而不是证书本身。您的代码示例似乎正在使用证书本身:
keyInfo = xmlSignature.getKeyInfo();
X509CertificateResolverCN = "org.apache.xml.security.keys.keyresolver.implementations.X509CertificateResolver";
keyResolver = CreateObject("Java", X509CertificateResolverCN).init();
keyInfo.registerInternalKeyResolver(keyResolver);
x509cert = keyInfo.getX509Certificate();
isValid = xmlSignature.checkSignatureValue(x509cert);
如何调整此设置以使用X509证书中的java.security.PublicKey:
免责声明:我一生中从未写过一行CF,因此,如果它可以工作,但需要进行调整,请发表评论,我将对其进行调整。如果它无法验证或您无法解析ID为的元素。请添加下面的第三行。现在的情况是,较新版本的Apache Santuario不再假定IdAttribute是ID。您需要手动设置它
xmlResponse = getHttpRequestData().content.Trim();
docElement = XmlParse(variables.xmlResponse);
docElement.setIdAttribute("ID",true); //Add this line
除了上面的代码片段之外,您是否执行过任何配置?我不知道ColdFusion,但是您需要以某种方式注册或引用来自IdP的已知公钥,以便您的Java代码能够解析和验证数字签名是否有效,或者是否确实是从IdP的私钥创建的。在其他服务器运行时(如JavaEE应用程序服务器)中,这通常是导入公钥的配置步骤。在独立的Java程序中,我通常看到这样做是通过对Internet上Java密钥库文件lotsss的文件引用来完成的。我怀疑您在这方面是正确的。然而,每当我看到任何关于验证断言的微不足道的ColdFusion示例时,它们都没有提到任何关于密钥库的内容。也许只是假设读者已经设置好了。看起来我还有更多的研究要做,因为我不知道如何使用密钥库。看看这些代码,我敢打赌它期望公钥出现在断言中。同意-你能发布你得到的示例断言吗?另外,在您列出的博客文章的底部,有一个从文件系统加载Java密钥存储的示例。通过java keytool命令加载/创建java密钥库文件的一个很好的教程是。@scotth-只是好奇而已。他们必须从他们的密钥库中获取密钥吗,或者仅仅是这样吗?我将接受这个答案,因为我能找到的唯一解决方案是使用稍微旧一点的Santuario库版本。使用最新的库不起作用。。。因此,上述解决方案可能是正确的答案。
xmlResponse = getHttpRequestData().content.Trim();
docElement = XmlParse(variables.xmlResponse);
docElement.setIdAttribute("ID",true); //Add this line