Java 基于SAML请求创建SAML响应
我已经开发了一个JavaWeb应用程序,我想实现SAML。我认为这些是实现SAML的正确步骤Java 基于SAML请求创建SAML响应,java,saml,saml-2.0,assertions,Java,Saml,Saml 2.0,Assertions,我已经开发了一个JavaWeb应用程序,我想实现SAML。我认为这些是实现SAML的正确步骤 服务提供者(SP,在本例中是我的应用程序)向IdP发送SAML身份验证请求 然后,IdP对其进行验证,创建SAML响应断言,并使用证书对其进行签名,然后发送回SP SP然后使用密钥库中证书的公钥对其进行验证,并在此基础上进一步进行 我有一个示例代码,我能够创建SAML请求,就像这样 <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="_c7b796f4-bc16-4fcc-8c1d-36befffc39c2" Version="2.0"
IssueInstant="2014-10-30T11:21:08Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="http://localhost:8080/mywebapp/consume.jsp">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8080/mywebapp
</saml:Issuer>
<samlp:NameIDPolicy
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"
AllowCreate="true"></samlp:NameIDPolicy>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
http://localhost:8080/mywebapp
urn:oasis:name:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
我可以对它进行编码并发送到IdP
我想创建示例Java代码来获取这个SAML请求,然后创建一个SAML响应。
如何解码请求、验证请求并创建响应?我需要用证书签署saml响应吗?然后发送回SP
谢谢。您列出的步骤或多或少都是正确的。我要指出的唯一一点是,如果单词sends(例如,“SP…向IdP发送SAML身份验证请求”)的含义,您必须小心。SAML允许SP和IdP之间零直接通信的身份验证场景 另一个小的补充是SP也可以签署他的请求,因此您可以在双方进行签名验证。SP端的验证是强制性的 例如,如果要实现SAML,可能需要检查现有的解决方案之一。如果你在Spring和JBoss这样的平台上,你可能想检查一下或者。如果你想去低一层,检查一下
在我的公司,JBoss是我们的标准配置,我们对此非常满意。您列出的步骤或多或少都是正确的。我要指出的唯一一点是,如果单词sends(例如,“SP…向IdP发送SAML身份验证请求”)的含义,您必须小心。SAML允许SP和IdP之间零直接通信的身份验证场景 另一个小的补充是SP也可以签署他的请求,因此您可以在双方进行签名验证。SP端的验证是强制性的 例如,如果要实现SAML,可能需要检查现有的解决方案之一。如果你在Spring和JBoss这样的平台上,你可能想检查一下或者。如果你想去低一层,检查一下
在我的公司里,JBoss是我们的标准配置,我们对此非常满意。虽然这是一篇老文章,但我正在添加一些示例代码和参考资料,我发现它们很有用
SAMLResponse = hreq.getParameter("SAMLResponse");
InputSource inputSource = new InputSource(new StringReader(SAMLResponse));
SAMLReader samlReader = new SAMLReader();
response2 = org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
现在验证数字签名:
org.opensaml.saml2.core.Response response2 = (org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
//To fetch the digital signature from the response.
Signature signature = response2.getSignature();
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(domainName);
//pull out the public key part of the certificate into a KeySpec
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());
//get KeyFactory object that creates key objects, specifying RSA - java.security.KeyFactory
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//generate public key to validate signatures
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
//we have the public key
BasicX509Credential publicCredential = new BasicX509Credential();
//add public key value
publicCredential.setPublicKey(publicKey);
//create SignatureValidator
SignatureValidator signatureValidator = new SignatureValidator(publicCredential);
//try to validate
try{
signatureValidator.validate(signature);
catch(Exception e){
//
}
现在获取断言映射:
samlDetailsMap = setSAMLDetails(response2);
在上面的逻辑中,使用下面的私有方法来提取所有断言属性。最后,您将拥有发送给您的所有字段的地图
private Map<String, String> setSAMLDetails(org.opensaml.saml2.core.Response response2){
Map<String, String> samlDetailsMap = new HashMap<String, String>();
try {
List<Assertion> assertions = response2.getAssertions();
LOGGER.error("No of assertions : "+assertions.size());
for(Assertion assertion:assertions){
List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
for(AttributeStatement attributeStatement: attributeStatements){
List<Attribute> attributes = attributeStatement.getAttributes();
for(Attribute attribute: attributes){
String name = attribute.getName();
List<XMLObject> attributes1 = attribute.getAttributeValues();
for(XMLObject xmlObject : attributes1){
if(xmlObject instanceof XSString){
samlDetailsMap.put(name, ((XSString) xmlObject).getValue());
LOGGER.error("Name is : "+name+" value is : "+((XSString) xmlObject).getValue());
}else if(xmlObject instanceof XSAnyImpl){
String value = ((XSAnyImpl) xmlObject).getTextContent();
samlDetailsMap.put(name, value);
}
}
}
}
}
} catch (Exception e) {
LOGGER.error("Exception occurred while setting the saml details");
}
LOGGER.error("Exiting from setSAMLDetails method");
return samlDetailsMap;
}
}虽然这是一篇老文章,但我添加了一些我觉得有用的示例代码和参考资料
SAMLResponse = hreq.getParameter("SAMLResponse");
InputSource inputSource = new InputSource(new StringReader(SAMLResponse));
SAMLReader samlReader = new SAMLReader();
response2 = org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
现在验证数字签名:
org.opensaml.saml2.core.Response response2 = (org.opensaml.saml2.core.Response)samlReader.readFromFile(inputSource);
//To fetch the digital signature from the response.
Signature signature = response2.getSignature();
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(domainName);
//pull out the public key part of the certificate into a KeySpec
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());
//get KeyFactory object that creates key objects, specifying RSA - java.security.KeyFactory
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//generate public key to validate signatures
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
//we have the public key
BasicX509Credential publicCredential = new BasicX509Credential();
//add public key value
publicCredential.setPublicKey(publicKey);
//create SignatureValidator
SignatureValidator signatureValidator = new SignatureValidator(publicCredential);
//try to validate
try{
signatureValidator.validate(signature);
catch(Exception e){
//
}
现在获取断言映射:
samlDetailsMap = setSAMLDetails(response2);
在上面的逻辑中,使用下面的私有方法来提取所有断言属性。最后,您将拥有发送给您的所有字段的地图
private Map<String, String> setSAMLDetails(org.opensaml.saml2.core.Response response2){
Map<String, String> samlDetailsMap = new HashMap<String, String>();
try {
List<Assertion> assertions = response2.getAssertions();
LOGGER.error("No of assertions : "+assertions.size());
for(Assertion assertion:assertions){
List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
for(AttributeStatement attributeStatement: attributeStatements){
List<Attribute> attributes = attributeStatement.getAttributes();
for(Attribute attribute: attributes){
String name = attribute.getName();
List<XMLObject> attributes1 = attribute.getAttributeValues();
for(XMLObject xmlObject : attributes1){
if(xmlObject instanceof XSString){
samlDetailsMap.put(name, ((XSString) xmlObject).getValue());
LOGGER.error("Name is : "+name+" value is : "+((XSString) xmlObject).getValue());
}else if(xmlObject instanceof XSAnyImpl){
String value = ((XSAnyImpl) xmlObject).getTextContent();
samlDetailsMap.put(name, value);
}
}
}
}
}
} catch (Exception e) {
LOGGER.error("Exception occurred while setting the saml details");
}
LOGGER.error("Exiting from setSAMLDetails method");
return samlDetailsMap;
}
}我想测试我的应用程序。我已经创建了SAML请求。我尝试了一些IdP,但不是免费的。所以我尝试创建自己的SAML响应。我有一份证书样本。我想在回复上签名并发送到我的应用程序。我想你可以免费使用SalesForce进行测试。这里是PicketLink的文档,但您也可以将其应用于SP:如何使用java代码从SAMLResponse获取Samlasertion?我想测试我的应用程序。我已经创建了SAML请求。我尝试了一些IdP,但不是免费的。所以我尝试创建自己的SAML响应。我有一份证书样本。我想在回复上签名并发送到我的应用程序。我想你可以免费使用SalesForce进行测试。这里是PicketLink的文档,但您也可以将其应用于SP:我们如何使用java代码从SAMLResponse获取Samlasertion?