基于SAML请求创建SAML响应
问题描述:
我开发了一个Java Web应用程序,并且我想实施SAML。这些是我认为正确实施SAML的步骤。基于SAML请求创建SAML响应
- 服务提供商(SP,我的应用程序在这种情况下)向IdP发送SAML身份验证请求。
- 然后,IdP验证它并创建一个SAML响应声明并将其与证书签名并发送回SP。
- SP随后使用密钥库中的证书的公钥对其进行验证,然后基于此证据进行进一步处理。
我有一个示例代码,我能够创造SAML请求及其类似这样
<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>
我可以编码并发送国内流离失所者。
我想创建示例Java代码来获取此SAML请求,然后创建一个SAML响应。 如何解码请求并验证它并创建响应?我是否需要在证书上签名saml回复?然后发送回SP?
谢谢。
答
您列出的步骤或多或少都正确。我唯一指出的是,如果单词发送(例如“SP ...向IdP发送SAML身份验证请求”),则必须注意含义。 SAML允许身份验证方案与SP和IdP之间的零直接通信。
另一个小的补充是,SP也可以签署他的请求,所以你可能在双方都有签名验证。 SP方面的验证是强制性的。
如果要实施SAML,可能需要检查其中一个现有解决方案,例如Shibboleth。如果你使用Spring和JBoss平台,你可能需要检查Spring Security SAML或JBoss PicketLink。如果您想要更低级别,请选择OpenSAML。
在我的公司,我们有JBoss作为标准,并且对PicketLink非常满意。
答
虽然这是一个旧帖子,但我添加了示例代码和引用,我发现它们很有用。
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;
}
添加如下新类SAMLReader:
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.opensaml.DefaultBootstrap;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.io.UnmarshallingException;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class SAMLReader {
private static DocumentBuilder builder;
static{
try{
DefaultBootstrap.bootstrap();
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware (true);
builder = factory.newDocumentBuilder();
}catch (Exception ex){
ex.printStackTrace();
}
}
/**
*
* @param filename
* @return
* @throws IOException
* @throws UnmarshallingException
* @throws SAXException
*/
public XMLObject readFromFile (String filename)
throws IOException, UnmarshallingException, SAXException{
return fromElement (builder.parse (filename).getDocumentElement());
}
/**
*
* @param is
* @return
* @throws IOException
* @throws UnmarshallingException
* @throws SAXException
*/
public XMLObject readFromFile (InputStream is)
throws IOException, UnmarshallingException, SAXException{
return fromElement (builder.parse (is).getDocumentElement());
}
/**
*
* @param is
* @return
* @throws IOException
* @throws UnmarshallingException
* @throws SAXException
*/
public XMLObject readFromFile (InputSource is)
throws IOException, UnmarshallingException, SAXException{
return fromElement (builder.parse (is).getDocumentElement());
}
/**
*
* @param element
* @return
* @throws IOException
* @throws UnmarshallingException
* @throws SAXException
*/
public static XMLObject fromElement (Element element)
throws IOException, UnmarshallingException, SAXException{
return Configuration.getUnmarshallerFactory()
.getUnmarshaller (element).unmarshall (element);
}
}
我想测试我的应用程序。我已经创建了SAML请求。我尝试过一些IdP,但它不是免费的。所以我正在尝试创建自己的SAML响应。我有一个样品证书。我想签署回复并发送给我的申请。 – iUser 2014-10-30 08:56:23
我想你可以免费使用SalesForce进行测试。以下是PicketLink的文档,但您也可以将其应用于SP:https://docs.jboss.org/author/display/PLINK/Picketlink+as+SP,+Salesforce+as+IDP – lexicore 2014-10-30 09:21:43
我们如何获得SAMLAssertion从SAMLResponse使用Java代码? – 2015-04-10 06:10:26