Opa velho, eu ja tentei isso e não foi… vou postar meu servlet aqui…
Falow
package servlets;
import org.apache.commons.codec.binary.Base64;
import org.jdom.Document;
import util.SamlException;
import util.Util;
import util.XmlDigitalSigner;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This servlet, part of the SAML-based Single Sign-On Reference Tool, takes in
* a SAML AuthnRequest and verifies the user login credentials. Upon succesful
* user login, it generates and signs the corresponding SAML Response, which is
* then redirected to the specified Assertion Consumer Service.
*
*/
public class ProcessResponseServlet extends HttpServlet {
private final String samlResponseTemplateFile = "SamlResponseTemplate.xml";
private static final String domainName = "facsumare.com.br";
/*
* The login method should either return a null string, if the user is not
* successfully authenticated, or the user's username if the user is
* successfully authenticated.
*/
private String login(String username, String password) {
// Stage II: Update this method to call your authentication mechanism.
// Return username for successful authentication. Return null string
// for failed authentication.
return "";
}
/*
* Retrieves the AuthnRequest from the encoded and compressed String extracted
* from the URL. The AuthnRequest XML is retrieved in the following order: <p>
* 1. URL decode <br> 2. Base64 decode <br> 3. Inflate <br> Returns the String
* format of the AuthnRequest XML.
*/
private String decodeAuthnRequestXML(String encodedRequestXmlString)
throws SamlException {
try {
// URL decode
// No need to URL decode: auto decoded by request.getParameter() method
// Base64 decode
Base64 base64Decoder = new Base64();
byte[] xmlBytes = encodedRequestXmlString.getBytes("UTF-8");
byte[] base64DecodedByteArray = base64Decoder.decode(xmlBytes);
//Uncompress the AuthnRequest data
//First attempt to unzip the byte array according to DEFLATE (rfc 1951)
try {
Inflater inflater = new Inflater(true);
inflater.setInput(base64DecodedByteArray);
// since we are decompressing, it's impossible to know how much space we
// might need; hopefully this number is suitably big
byte[] xmlMessageBytes = new byte[5000];
int resultLength = inflater.inflate(xmlMessageBytes);
if (!inflater.finished()) {
throw new RuntimeException("didn't allocate enough space to hold "
+ "decompressed data");
}
inflater.end();
return new String(xmlMessageBytes, 0, resultLength, "UTF-8");
} catch (DataFormatException e) {
// if DEFLATE fails, then attempt to unzip the byte array according to
// zlib (rfc 1950)
ByteArrayInputStream bais = new ByteArrayInputStream(
base64DecodedByteArray);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InflaterInputStream iis = new InflaterInputStream(bais);
byte[] buf = new byte[1024];
int count = iis.read(buf);
while (count != -1) {
baos.write(buf, 0, count);
count = iis.read(buf);
}
iis.close();
return new String(baos.toByteArray());
}
} catch (UnsupportedEncodingException e) {
throw new SamlException("Error decoding AuthnRequest: " +
"Check decoding scheme - " + e.getMessage());
} catch (IOException e) {
throw new SamlException("Error decoding AuthnRequest: " +
"Check decoding scheme - " + e.getMessage());
}
}
/*
* Creates a DOM document from the specified AuthnRequest xmlString and
* extracts the value under the "AssertionConsumerServiceURL" attribute
*/
private String[] getRequestAttributes(String xmlString) throws SamlException {
Document doc = Util.createJdomDoc(xmlString);
if (doc != null) {
String[] samlRequestAttributes = new String[3];
samlRequestAttributes[0] = doc.getRootElement().getAttributeValue(
"IssueInstant");
samlRequestAttributes[1] = doc.getRootElement().getAttributeValue(
"ProviderName");
samlRequestAttributes[2] = doc.getRootElement().getAttributeValue(
"AssertionConsumerServiceURL");
return samlRequestAttributes;
} else {
throw new SamlException("Error parsing AuthnRequest XML: Null document");
}
}
/*
* Generates a SAML response XML by replacing the specified username on the
* SAML response template file. Returns the String format of the XML file.
*/
private String createSamlResponse(String authenticatedUser, String notBefore,
String notOnOrAfter) throws SamlException {
String filepath = getServletContext().getRealPath(
"templates/" + samlResponseTemplateFile);
String samlResponse = Util.readFileContents(filepath);
samlResponse = samlResponse.replace("<USERNAME_STRING>", authenticatedUser);
samlResponse = samlResponse.replace("<RESPONSE_ID>", Util.createID());
samlResponse = samlResponse.replace("<ISSUE_INSTANT>", Util
.getDateAndTime());
samlResponse = samlResponse.replace("<AUTHN_INSTANT>", Util
.getDateAndTime());
samlResponse = samlResponse.replace("<NOT_BEFORE>", notBefore);
samlResponse = samlResponse.replace("<NOT_ON_OR_AFTER>", notOnOrAfter);
samlResponse = samlResponse.replace("<ASSERTION_ID>", Util.createID());
return samlResponse;
}
/*
* Signs the SAML response XML with the specified private key, and embeds with
* public key. Uses helper class XmlDigitalSigner to digitally sign the XML.
*/
private String signResponse(String response, DSAPublicKey publicKey,
DSAPrivateKey privateKey) throws SamlException {
return (XmlDigitalSigner.signXML(response, publicKey, privateKey));
}
/*
* Checks if the specified samlDate is formatted as per the SAML 2.0
* specifications, namely YYYY-MM-DDTHH:MM:SSZ.
*/
private boolean validSamlDateFormat(String samlDate) {
if (samlDate == null) {
return false;
}
int indexT = samlDate.indexOf("T");
int indexZ = samlDate.indexOf("Z");
if (indexT != 10 || indexZ != 19) {
return false;
}
String dateString = samlDate.substring(0, indexT);
String timeString = samlDate.substring(indexT + 1, indexZ);
SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
ParsePosition pos = new ParsePosition(0);
Date parsedDate = dayFormat.parse(dateString, pos);
pos = new ParsePosition(0);
Date parsedTime = timeFormat.parse(timeString, pos);
if (parsedDate == null || parsedTime == null) {
return false;
}
return true;
}
/**
* The doGet method handles HTTP GET requests sent to the
* ProcessResponseServlet. This method's sole purpose is to interact with the
* user interface that allows you to walk through the steps of the reference
* implementation. In a production environment, Google's would send SAML
* requests using HTTP POST requests.
*
* This method receives an HTTP GET request and then forwards that request on
* to the identity_provider.jsp file, which is included in Google's SAML
* reference package. If this method receives a SAML request Read in SAML
* AuthnRequest parameters from request and generate signed SAML response to
* post to the Assertion Consumer Service.
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String SAMLRequest = request.getParameter("SAMLRequest");
String relayStateURL = request.getParameter("RelayState");
if (SAMLRequest != null) {
try {
String requestXmlString = decodeAuthnRequestXML(SAMLRequest);
String[] samlRequestAttributes = getRequestAttributes(requestXmlString);
String issueInstant = samlRequestAttributes[0];
String providerName = samlRequestAttributes[1];
String acsURL = samlRequestAttributes[2];
request.setAttribute("issueInstant", issueInstant);
request.setAttribute("providerName", providerName);
request.setAttribute("acsURL", acsURL);
request.setAttribute("relayStateURL", relayStateURL);
} catch (SamlException e) {
request.setAttribute("error", e.getMessage());
}
}
String returnPage = "./identity_provider.jsp";
request.getRequestDispatcher(returnPage).include(request, response);
}
/**
* The doPost method handles HTTP POST requests sent to the
* ProcessResponseServlet. It then works to generate a SAML response with the
* received parameter and then post the response to the Assertion Consumer
* Service.
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String samlAction = request.getParameter("samlAction");
String SAMLRequest = request.getParameter("SAMLRequest");
String returnPage = request.getParameter("returnPage");
String username = request.getParameter("username");
String password = request.getParameter("password");
String relayStateURL = request.getParameter("RelayState");
boolean continueLogin = true;
if (SAMLRequest == null || SAMLRequest.equals("null")) {
continueLogin = false;
request.setAttribute("error", "ERROR: Unspecified SAML parameters.");
} else if (samlAction == null) {
continueLogin = false;
request.setAttribute("error", "ERROR: Invalid SAML action.");
} else if (returnPage != null) {
try {
// Parse the SAML request and extract the ACS URL and provider name
// Extract the Assertion Consumer Service URL from AuthnRequest
String requestXmlString = decodeAuthnRequestXML(SAMLRequest);
String[] samlRequestAttributes = getRequestAttributes(requestXmlString);
String issueInstant = samlRequestAttributes[0];
String providerName = samlRequestAttributes[1];
String acsURL = samlRequestAttributes[2];
/*
* Stage II: Whereas Stage I uses a hardcoded username
* (demouser@psosamldemo.net), in Stage II you need to modify the code
* to call your user authentication application.
*/
username = login(username, password);
// The following lines of code set variables used in the UI.
request.setAttribute("issueInstant", issueInstant);
request.setAttribute("providerName", providerName);
request.setAttribute("acsURL", acsURL);
request.setAttribute("domainName", domainName);
request.setAttribute("username", username);
request.setAttribute("relayStateURL", relayStateURL);
if (username == null) {
request.setAttribute("error", "Login Failed: Invalid user.");
} else {
// Acquire public and private DSA keys
/*
* Stage III: Update the DSA filenames to identify the locations of
* the DSA/RSA keys that digitally sign SAML responses for your
* domain. The keys included in the reference implementation sign SAML
* responses for the psosamldemo.net domain.
*/
String publicKeyFilePath = getServletContext().getRealPath(
"./keys/DSAPublicKey01.key");
String privateKeyFilePath = getServletContext().getRealPath(
"./keys/DSAPrivateKey01.key");
DSAPublicKey publicKey = (DSAPublicKey) Util.getPublicKey(
publicKeyFilePath, "DSA");
DSAPrivateKey privateKey = (DSAPrivateKey) Util.getPrivateKey(
privateKeyFilePath, "DSA");
// Check for valid parameter values for SAML response
// First, verify that the NotBefore and NotOnOrAfter values are valid
String notBefore = "2003-04-17T00:46:02Z";
String notOnOrAfter = "2008-04-17T00:51:02Z";
request.setAttribute("notBefore", notBefore);
request.setAttribute("notOnOrAfter", notOnOrAfter);
if (!validSamlDateFormat(issueInstant)) {
continueLogin = false;
request.setAttribute("error",
"ERROR: Invalid NotBefore date specified - " + notBefore);
} else if (!validSamlDateFormat(notOnOrAfter)) {
continueLogin = false;
request.setAttribute("notOnOrAfter", "2008-04-17T00:51:02Z");
request.setAttribute("error",
"ERROR: Invalid NotOnOrAfter date specified - " + notOnOrAfter);
}
// Sign XML containing user name with specified keys
if (continueLogin) {
// Generate SAML response contaning specified user name
String responseXmlString = createSamlResponse(username, notBefore,
notOnOrAfter);
// Sign the SAML response XML
String signedSamlResponse = signResponse(responseXmlString,
publicKey, privateKey);
request.setAttribute("samlResponse", signedSamlResponse);
}
}
} catch (SamlException e) {
request.setAttribute("error", e.getMessage());
}
}
// Forward SAML response to ACS
request.getRequestDispatcher(returnPage).include(request, response);
}
}