【发布时间】:2019-11-27 14:35:34
【问题描述】:
我已在此处发布了我实现的代码。当我单击特定 URL Ex:(https://wwwdev-lom.app.ford.com/launchomatic/launch/view.jsp?chronicleId=0900cad780aaac86&docbase=edmsdev) 时,我正在初始化 SAML servlet,但是当我单击身份验证 SAML 时,页面重定向回 ADFS 页面。ADFS 页面已成功通过身份验证。我希望将页面重定向回我单击的同一 URL。该链接应该帮助我在验证 ADFS 后从浏览器下载内容。我是否应该通过 JSP a 再次构建此 URL 并转发此 servlet到 JSP。如果是这样,我如何从当前的 servlet(下一个)调用到 JSP,我在下面的哪里调用它?
import com.documentum.com.DfClientX;
import com.ford.launchomatic.downloader.LaunchFile;
import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.common.IDfLoginInfo;
import com.documentum.wc.env.jsp.DwJSPPageContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.joda.time.DateTime;
import org.opensaml.DefaultBootstrap;
import org.opensaml.common.SAMLVersion;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.StatusMessage;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.SubjectConfirmation;
import org.opensaml.saml2.core.SubjectConfirmationData;
import org.opensaml.saml2.core.impl.AuthnRequestBuilder;
import org.opensaml.saml2.core.impl.IssuerBuilder;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.x509.BasicX509Credential;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.util.Base64;
import org.opensaml.xml.util.XMLHelper;
import org.opensaml.xml.validation.ValidationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class AuthenticateSAML extends HttpServlet
{
private static final long serialVersionUID = 1L;
String path = null;
static PrintWriter log;
Properties prop;
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
this.path = servletConfig.getServletContext().getRealPath(
"/WEB-INF/classes/saml.properties");
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doPost(request, response); }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
InputStream inputStream = null;
try {
PrintWriter pw = response.getWriter();
this.prop = new Properties();
inputStream = new FileInputStream(this.path);
this.prop.load(inputStream);
inputStream.close();
String logFile = this.prop.getProperty("logFile");
createLog(logFile);
Trace("==========START SAML SSO==========");
Trace("Creating Authentication Request");
String url = buildAuthenticationRequest(request,response);
response.sendRedirect(url);
String value = request.getParameter("SAMLResponse");
if(validateResponse("xxxx",value))
{
Trace("SAML response validated successful");
}
String docbase = this.prop.getProperty("docbase");
Boolean docbasesuccess = DFCAuthentication("xxxx", value, docbase);
if(docbasesuccess)
{
Trace("docbase authentication successful");
}
if (log != null) {
log.flush();
log.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
public String buildAuthenticationRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
DefaultBootstrap.bootstrap();
String IDPurl = this.prop.getProperty("IDPurl");
String ACSurl = request.getRequestURL().toString();
String issuerURL = this.prop.getProperty("Issuer");
IssuerBuilder issuerBuilder = new IssuerBuilder();
Issuer issuer = issuerBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:assertion", "Issuer", "saml");
issuer.setValue(issuerURL);
DateTime issueInstant = new DateTime();
AuthnRequestBuilder authnRequestBuilder = new AuthnRequestBuilder();
AuthnRequest authnRequest = authnRequestBuilder.buildObject();
authnRequest.setForceAuthn(new Boolean(false));
authnRequest.setIsPassive(new Boolean(false));
authnRequest.setIssueInstant(issueInstant);
authnRequest.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
authnRequest.setAssertionConsumerServiceURL(ACSurl);
authnRequest.setIssuer(issuer);
authnRequest.setID("AQ1");
authnRequest.setVersion(SAMLVersion.VERSION_20);
Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller((XMLObject)authnRequest);
Element authDOM = marshaller.marshall((XMLObject)authnRequest);
authDOM.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve");
StringWriter rspWrt = new StringWriter();
XMLHelper.writeNode(authDOM, rspWrt);
String requestMessage = rspWrt.toString();
Deflater deflater = new Deflater(8, true);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
deflaterOutputStream.write(requestMessage.getBytes());
deflaterOutputStream.close();
String encodedRequestMessage = Base64.encodeBytes(byteArrayOutputStream.toByteArray(), 8);
String encodedAuthnRequest = URLEncoder.encode(encodedRequestMessage, "UTF-8");
String url = String.valueOf(IDPurl) + "/?SAMLRequest=" + encodedAuthnRequest;
return url;
}
static void Trace(String info) {
if (log != null) {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS");
log.write(String.valueOf(dateFormat.format(date)) + " " + info);
log.write(System.lineSeparator());
}
}
static void createLog(String fileName) {
try {
File logFile = new File(fileName);
File logDir = new File(logFile.getParent());
if (!logDir.exists())
logDir.mkdir();
FileWriter fw = new FileWriter(fileName, true);
log = new PrintWriter(fw);
} catch (IOException e) {
e.printStackTrace();
}
}
public static ArrayList<String> listFilesForFolder(File folder) {
ArrayList<String> certList = new ArrayList<>();
int flag = 0;
if (folder == null || !folder.exists()) {
Trace("Cannot load certificates. Folder doesn't exist: " +
folder.getAbsolutePath());
return null;
}
Trace("Retrieving Certificates in folder: " + folder.getAbsolutePath()); byte b; int i; File[] arrayOfFile;
for (i = (arrayOfFile = folder.listFiles()).length, b = 0; b < i; ) { File fileEntry = arrayOfFile[b];
if (!fileEntry.isDirectory()) {
String path = fileEntry.getAbsolutePath();
String name = fileEntry.getName();
int extStart = name.lastIndexOf(".");
if (extStart != -1) {
String ext = name.substring(extStart + 1);
if (ext.equalsIgnoreCase("crt") ||
ext.equalsIgnoreCase("cer") ||
ext.equalsIgnoreCase("der")) {
flag = 1;
certList.add(path);
}
}
} b++; }
if (flag == 0) {
Trace("No certificates found...");
return null;
}
return certList;
}
public boolean isNullorEmpty(String value) { return !(value != null && value.trim() != ""); }
public boolean validateResponse(String username, String responseMessage) throws Exception {
InputStream inputStream = null;
try {
if (this.prop == null)
this.prop = new Properties();
inputStream = new FileInputStream(this.path);
this.prop.load(inputStream);
inputStream.close();
String certPath = this.prop.getProperty("certPath");
Trace("User: " + username);
if (isNullorEmpty(username) || isNullorEmpty(responseMessage)) {
Trace("Username or SAMLToken cannot be null");
Trace("Authentication failure");
return false;
}
DefaultBootstrap.bootstrap();
byte[] base64DecodedResponse = Base64.decode(responseMessage);
ByteArrayInputStream is = new ByteArrayInputStream(
base64DecodedResponse);
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = documentBuilderFactory
.newDocumentBuilder();
Document document = docBuilder.parse(is);
Element element = document.getDocumentElement();
UnmarshallerFactory unmarshallerFactory =
Configuration.getUnmarshallerFactory();
Unmarshaller unmarshaller = unmarshallerFactory
.getUnmarshaller(element);
XMLObject responseXmlObj = unmarshaller.unmarshall(element);
Response samlresponse = (Response)responseXmlObj;
String statusCode = samlresponse.getStatus().getStatusCode()
.getValue();
Trace("Response status: " + statusCode);
if (!statusCode.equals("urn:oasis:names:tc:SAML:2.0:status:Success")) {
StatusMessage statusMessage = samlresponse.getStatus().getStatusMessage();
Trace("Status code is not success");
if (statusMessage != null) {
String statusMessageText = null;
statusMessageText = statusMessage.getMessage();
Trace("Reason: " + statusMessageText);
}
Trace("Authentication failure");
return false;
}
Assertion assertion = null;
Signature signature = null;
List<Assertion> assertionList = samlresponse.getAssertions();
if (assertionList.isEmpty()) {
List<EncryptedAssertion> encassertionList = samlresponse
.getEncryptedAssertions();
if (encassertionList.isEmpty()) {
Trace("Problem with retrieveing assertion/encrypted assertion from the provided SAML response");
Trace("Authentication failure");
return false;
}
Trace("Encrypted Assertion is not supported right now. Please turn off encrypted assertion at the IdP");
return false;
}
assertion = assertionList.get(0);
if (assertion == null) {
Trace("The Response must contain at least one Assertion");
Trace("Authentication failure");
return false;
}
if (!assertion.isSigned() && !samlresponse.isSigned()) {
Trace("Either assertion or response has to be signed ");
Trace("Authentication failure");
return false;
}
signature = assertion.getSignature();
if (signature == null) {
signature = samlresponse.getSignature();
if (signature == null) {
Trace("Problem retrieving signature from the provided SAML response.");
Trace("Authentication failure");
return false;
}
}
ArrayList<String> certList = listFilesForFolder(new File(certPath));
if (certList == null) {
Trace("Authentication failure");
return false;
}
int success = 0;
for (String name : certList) {
Trace("Validating signature with certificate: " + name);
File certificateFile = new File(name);
SignatureValidator signatureValidator = null;
X509EncodedKeySpec publicKeySpec = null;
FileInputStream certInputStream = null;
try {
certInputStream = new FileInputStream(certificateFile);
CertificateFactory certificateFactory =
CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)certificateFactory
.generateCertificate(certInputStream);
publicKeySpec = new X509EncodedKeySpec(certificate
.getPublicKey().getEncoded());
} catch (CertificateException ce) {
Trace("Signature verificaton: Failure");
Trace("Reason: " + ce.getMessage());
continue;
} catch (FileNotFoundException e) {
Trace("Signature verificaton: Failure");
Trace("Reason: " + e.getMessage());
continue;
}
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory
.generatePublic(publicKeySpec);
BasicX509Credential publicCredential = new BasicX509Credential();
publicCredential.setPublicKey(publicKey);
signatureValidator = new SignatureValidator(
(Credential)publicCredential);
signatureValidator.validate(signature);
Trace("Signature verification: Success");
success = 1;
break;
} catch (ValidationException e) {
Trace("Invalid Signature");
Trace("Reason: " + e.getMessage());
}
}
if (success == 0) {
Trace("Signature doesn't match with any of the available certificates");
Trace("Authentication failure");
return false;
}
if (assertion.getConditions() != null) {
DateTime validFrom = assertion.getConditions().getNotBefore();
DateTime validTill = assertion.getConditions()
.getNotOnOrAfter();
if (validFrom != null && validFrom.isAfterNow()) {
Trace("Assertion is not yet valid, invalidated by condition notBefore");
Trace("Authentication failure");
return false;
}
if (validTill != null && (
validTill.isBeforeNow() || validTill.isEqualNow())) {
Trace("Assertion is no longer valid, invalidated by condition notOnOrAfter");
Trace("Authentication failure");
return false;
}
}
success = 0;
Subject subject = assertion.getSubject();
if (subject == null) {
Trace("Assertion subject cannot be null");
Trace("Authentication failure");
return false;
}
try {
String nameID = subject.getNameID().getValue();
if (!nameID.equalsIgnoreCase(username)) {
Trace("UserName doesn't match with the NameID in Assertion");
Trace("Authentication failure");
return false;
}
} catch (Exception e) {
Trace("Problem retrieving NameID from Assertion's subject");
Trace("Authentication failure");
return false;
}
Iterator<SubjectConfirmation> iterator = subject.getSubjectConfirmations().iterator(); while (iterator.hasNext()) { SubjectConfirmation confirmation = iterator.next();
if ("urn:oasis:names:tc:SAML:2.0:cm:bearer".equals(confirmation
.getMethod())) {
SubjectConfirmationData data = confirmation
.getSubjectConfirmationData();
if (data == null) {
Trace("Bearer SubjectConfirmation invalidated by missing confirmation data");
continue;
}
if (data.getNotBefore() != null) {
Trace("Bearer SubjectConfirmation invalidated by not before which is forbidden");
continue;
}
DateTime expiry = data.getNotOnOrAfter();
if (expiry == null) {
Trace("Bearer SubjectConfirmation invalidated by missing notOnOrAfter");
continue;
}
if (expiry.isBeforeNow() || expiry.isEqualNow()) {
Trace("Bearer SubjectConfirmation invalidated by notOnOrAfter");
continue;
}
success = 1;
break;
} }
if (success == 0) {
Trace("Not able to validate subject confirmation");
Trace("Authentication failure");
return false;
}
Trace("Authentication success");
return true;
} catch (Exception e) {
Trace("Authentication failure");
Trace("Reason: " + e.getMessage());
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
public boolean DFCAuthentication(String user, String password, String docbase) {
IDfSessionManager sessionManager = null;
IDfSession session = null;
System.out.println("Calling docbase authentication+++++++");
try {
DfClientX dfClientX = new DfClientX();
IDfClient client = DfClient.getLocalClient();
sessionManager = client.newSessionManager();
IDfLoginInfo loginInfo = dfClientX.getLoginInfo();
loginInfo.setUser(user);
String pass = "dm_saml=" + password;
Trace(pass);
loginInfo.setPassword(pass);
loginInfo.setDomain(null);
sessionManager.setIdentity(docbase, loginInfo);
session = sessionManager.getSession(docbase);
return true;
}
catch (Exception e) {
return false;
}
}
}
enter code here
【问题讨论】:
标签: saml