NIHVIVO-1207 Break the two-part Shibboleth process into two servlets.
This commit is contained in:
parent
f7b7046318
commit
9f9237aa64
4 changed files with 306 additions and 278 deletions
|
@ -0,0 +1,61 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all Login servlets, whether Shibboleth, CuWebAuth, etc.
|
||||||
|
*/
|
||||||
|
public class BaseLoginServlet extends HttpServlet {
|
||||||
|
private static final Log log = LogFactory.getLog(BaseLoginServlet.class);
|
||||||
|
|
||||||
|
protected Authenticator getAuthenticator(HttpServletRequest req) {
|
||||||
|
return Authenticator.getInstance(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store an error message in the login bean and go back where we came from.
|
||||||
|
*
|
||||||
|
* Remove the referring URL from the session after using it.
|
||||||
|
*/
|
||||||
|
protected void complainAndReturnToReferrer(HttpServletRequest req,
|
||||||
|
HttpServletResponse resp, String sessionAttributeForReferrer,
|
||||||
|
Message message, Object... args) throws IOException {
|
||||||
|
log.debug(message.getMessageLevel() + ": "
|
||||||
|
+ message.formatMessage(args));
|
||||||
|
LoginProcessBean.getBean(req).setMessage(message, args);
|
||||||
|
|
||||||
|
String referrer = (String) req.getSession().getAttribute(
|
||||||
|
sessionAttributeForReferrer);
|
||||||
|
log.debug("returning to referrer: " + referrer);
|
||||||
|
if (referrer == null) {
|
||||||
|
referrer = figureHomePageUrl(req);
|
||||||
|
log.debug("returning to home page: " + referrer);
|
||||||
|
}
|
||||||
|
|
||||||
|
req.getSession().removeAttribute(sessionAttributeForReferrer);
|
||||||
|
resp.sendRedirect(referrer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we don't have a referrer, send them to the home page.
|
||||||
|
*/
|
||||||
|
protected String figureHomePageUrl(HttpServletRequest req) {
|
||||||
|
StringBuffer url = req.getRequestURL();
|
||||||
|
String uri = req.getRequestURI();
|
||||||
|
int authLength = url.length() - uri.length();
|
||||||
|
String auth = url.substring(0, authLength);
|
||||||
|
return auth + req.getContextPath();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,278 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This servlet acts as the interface to the Shibboleth authentication server.
|
|
||||||
*
|
|
||||||
* If the request has the "setup" property, it is coming from the Vivo login
|
|
||||||
* screen and going to the Shibboleth server.
|
|
||||||
*
|
|
||||||
* Otherwise, the request is coming from the Shibboleth server and going back to
|
|
||||||
* Vivo.
|
|
||||||
*/
|
|
||||||
public class LoginShibboleth extends HttpServlet {
|
|
||||||
private static final Log log = LogFactory.getLog(LoginShibboleth.class);
|
|
||||||
|
|
||||||
private static final String CLASSNAME = LoginShibboleth.class.getName();
|
|
||||||
|
|
||||||
/** This session attribute tells where we came from. */
|
|
||||||
private static final String ATTRIBUTE_REFERRER = CLASSNAME + ".referrer";
|
|
||||||
|
|
||||||
/** This request parameter indicates that we are setting up the login. */
|
|
||||||
private static final String PARAMETER_SETUP = "setup";
|
|
||||||
|
|
||||||
/** This http header holds the referring page. */
|
|
||||||
private static final String HEADING_REFERRER = "referer";
|
|
||||||
|
|
||||||
/** On return froma Shibboleth login, this header holds the provider name. */
|
|
||||||
private static final String HEADING_SHIBBOLETH_PROVIDER = "shib-identity-provider";
|
|
||||||
|
|
||||||
/** On return froma Shibboleth login, this header holds the user name. */
|
|
||||||
private static final String HEADING_SHIBBOLETH_USERNAME = "glid";
|
|
||||||
|
|
||||||
/** The configuration property that points to the Shibboleth server. */
|
|
||||||
private static final String PROPERTY_SHIBBOLETH_SERVER_URL = "shibboleth.server.url";
|
|
||||||
|
|
||||||
/** The configuration property that tells what provider name we expect. */
|
|
||||||
private static final String PROPERTY_SHIBBOLETH_PROVIDER = "shibboleth.provider";
|
|
||||||
|
|
||||||
private static final Message MESSAGE_NO_SHIBBOLETH_SERVER = new LoginProcessBean.Message(
|
|
||||||
"deploy.properties doesn't contain a value for '"
|
|
||||||
+ PROPERTY_SHIBBOLETH_SERVER_URL + "'",
|
|
||||||
LoginProcessBean.MLevel.ERROR);
|
|
||||||
|
|
||||||
private static final Message MESSAGE_NO_SHIBBOLETH_PROVIDER = new LoginProcessBean.Message(
|
|
||||||
"deploy.properties doesn't contain a value for '"
|
|
||||||
+ PROPERTY_SHIBBOLETH_PROVIDER + "'",
|
|
||||||
LoginProcessBean.MLevel.ERROR);
|
|
||||||
|
|
||||||
private static final Message MESSAGE_LOGIN_FAILED = new LoginProcessBean.Message(
|
|
||||||
"Shibboleth login failed.", LoginProcessBean.MLevel.ERROR);
|
|
||||||
|
|
||||||
private static final Message MESSAGE_NO_SUCH_USER = new LoginProcessBean.Message(
|
|
||||||
"Shibboleth login succeeded, but user {0} is unknown to VIVO.",
|
|
||||||
LoginProcessBean.MLevel.ERROR);
|
|
||||||
|
|
||||||
private static final String ERROR_NO_PARAMETERS = "Likely error in the template: "
|
|
||||||
+ "'setup' parameter was not found, "
|
|
||||||
+ "but there was no info from the Shibboleth server either.";
|
|
||||||
|
|
||||||
private final LoginRedirector loginRedirector = new LoginRedirector();
|
|
||||||
|
|
||||||
private String shibbolethServerUrl;
|
|
||||||
private String shibbolethProvider;
|
|
||||||
private static boolean isFirstCallToServlet = true;
|
|
||||||
|
|
||||||
/** Get the configuration properties. */
|
|
||||||
@Override
|
|
||||||
public void init() throws ServletException {
|
|
||||||
shibbolethServerUrl = ConfigurationProperties
|
|
||||||
.getProperty(PROPERTY_SHIBBOLETH_SERVER_URL);
|
|
||||||
shibbolethProvider = ConfigurationProperties
|
|
||||||
.getProperty(PROPERTY_SHIBBOLETH_PROVIDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <pre>
|
|
||||||
* The first request to this servlet must include the setup parameter.
|
|
||||||
* If it doesn't, it is totally bogus and will cause a complaint.
|
|
||||||
* This means that the login form isn't coded correctly,
|
|
||||||
* We try to notify the sysadmin in a meaningful way.
|
|
||||||
*
|
|
||||||
* On setup, write down the referring page and redirect to the shib server URL
|
|
||||||
* a URL that comes from the deploy.properties via the widget code.
|
|
||||||
* if no such property, set error message and return to referring page.
|
|
||||||
* it returns to this page
|
|
||||||
*
|
|
||||||
* Not on setup
|
|
||||||
* check for the site name and the username
|
|
||||||
* if either is missing,
|
|
||||||
* return to the referring page with an error message: login failed.
|
|
||||||
* if both there and the provider is wrong
|
|
||||||
* return to the referring page with an error message: login failed.
|
|
||||||
* if both there and the user doesn't exist
|
|
||||||
* return to the referring page with an error message: no such user.
|
|
||||||
* otherwise (successful)
|
|
||||||
* record the login and redirect like we would on a normal login.
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
|
||||||
throws ServletException, IOException {
|
|
||||||
setupLoginProcessBean(req);
|
|
||||||
|
|
||||||
boolean setupParmIsSet = checkSetupParameterIsSet(req);
|
|
||||||
|
|
||||||
if (requestIsTotallyBogus(setupParmIsSet)) {
|
|
||||||
resp.sendError(500, ERROR_NO_PARAMETERS);
|
|
||||||
} else if (setupParmIsSet) {
|
|
||||||
settingUpShibbolethLogin(req, resp);
|
|
||||||
} else {
|
|
||||||
returningFromShibbolethLogin(req, resp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Record that the login is in progress. */
|
|
||||||
private void setupLoginProcessBean(HttpServletRequest req) {
|
|
||||||
LoginProcessBean bean = LoginProcessBean.getBean(req);
|
|
||||||
bean.setState(LoginProcessBean.State.LOGGING_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Does the request contain a "setup" parameter? */
|
|
||||||
private boolean checkSetupParameterIsSet(HttpServletRequest req) {
|
|
||||||
String setupParm = req.getParameter(PARAMETER_SETUP);
|
|
||||||
log.debug("setup=" + setupParm);
|
|
||||||
if ((setupParm == null) || setupParm.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If the first call doesn't include "setup", the template is broken. */
|
|
||||||
private boolean requestIsTotallyBogus(boolean setupParmIsSet) {
|
|
||||||
boolean bogosity = isFirstCallToServlet && !setupParmIsSet;
|
|
||||||
isFirstCallToServlet = false;
|
|
||||||
return bogosity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** On setup, hand over to the Shibboleth server. */
|
|
||||||
private void settingUpShibbolethLogin(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp) throws IOException {
|
|
||||||
storeTheReferringPage(req);
|
|
||||||
if (shibbolethServerUrl == null) {
|
|
||||||
log.debug("No shibboleth server in deploy.properties");
|
|
||||||
complainAndReturnToReferrer(req, resp, MESSAGE_NO_SHIBBOLETH_SERVER);
|
|
||||||
} else if (shibbolethProvider == null) {
|
|
||||||
log.debug("No shibboleth provider in deploy.properties");
|
|
||||||
complainAndReturnToReferrer(req, resp,
|
|
||||||
MESSAGE_NO_SHIBBOLETH_PROVIDER);
|
|
||||||
} else {
|
|
||||||
log.debug("Sending to shibboleth server.");
|
|
||||||
resp.sendRedirect(buildShibbolethRedirectUrl(req));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remember where we came from - we'll need to go back there. */
|
|
||||||
private void storeTheReferringPage(HttpServletRequest req) {
|
|
||||||
String referrer = req.getHeader(HEADING_REFERRER);
|
|
||||||
if (referrer == null) {
|
|
||||||
dumpRequestHeaders(req);
|
|
||||||
referrer = figureHomePageUrl(req);
|
|
||||||
}
|
|
||||||
log.debug("Referring page is '" + referrer + "'");
|
|
||||||
req.getSession().setAttribute(ATTRIBUTE_REFERRER, referrer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** How do we get to the Shibboleth server and back? */
|
|
||||||
private String buildShibbolethRedirectUrl(HttpServletRequest req) {
|
|
||||||
try {
|
|
||||||
String returnUrl = req.getRequestURL().toString();
|
|
||||||
String encodedReturnUrl = URLEncoder.encode(returnUrl, "UTF-8");
|
|
||||||
String shibbolethUrl = shibbolethServerUrl + "?target="
|
|
||||||
+ encodedReturnUrl;
|
|
||||||
log.debug("shibbolethURL is '" + shibbolethUrl + "'");
|
|
||||||
return shibbolethUrl;
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException(e); // No UTF-8? Really?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** On return from the Shibboleth server, try to apply the results. */
|
|
||||||
private void returningFromShibbolethLogin(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp) throws IOException {
|
|
||||||
String provider = req.getHeader(HEADING_SHIBBOLETH_PROVIDER);
|
|
||||||
String user = req.getHeader(HEADING_SHIBBOLETH_USERNAME);
|
|
||||||
log.debug("Info from Shibboleth: user=" + user + ", provider="
|
|
||||||
+ provider);
|
|
||||||
|
|
||||||
if ((provider == null) || (user == null)) {
|
|
||||||
complainAndReturnToReferrer(req, resp, MESSAGE_LOGIN_FAILED);
|
|
||||||
} else if (!this.shibbolethProvider.equals(provider)) {
|
|
||||||
log.error("Wrong shibboleth provider: " + provider);
|
|
||||||
complainAndReturnToReferrer(req, resp, MESSAGE_LOGIN_FAILED);
|
|
||||||
} else if (!getAuthenticator(req).isExistingUser(user)) {
|
|
||||||
log.debug("No such user: " + user);
|
|
||||||
complainAndReturnToReferrer(req, resp, MESSAGE_NO_SUCH_USER, user);
|
|
||||||
} else {
|
|
||||||
log.debug("Logging in as " + user);
|
|
||||||
recordLoginAndRedirect(req, resp, user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Success. Record the login and send them to the appropriate page. */
|
|
||||||
private void recordLoginAndRedirect(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp, String username)
|
|
||||||
throws UnsupportedEncodingException, IOException {
|
|
||||||
getAuthenticator(req).recordUserIsLoggedIn(username);
|
|
||||||
req.getSession().removeAttribute(ATTRIBUTE_REFERRER);
|
|
||||||
loginRedirector.redirectLoggedInUser(req, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Store an error message in the login bean and go back where we came from. */
|
|
||||||
private void complainAndReturnToReferrer(HttpServletRequest req,
|
|
||||||
HttpServletResponse resp, Message message, Object... args)
|
|
||||||
throws IOException {
|
|
||||||
log.debug(message.getMessageLevel() +": "+ message.formatMessage(args));
|
|
||||||
LoginProcessBean.getBean(req).setMessage(message, args);
|
|
||||||
|
|
||||||
String referrer = (String) req.getSession().getAttribute(
|
|
||||||
ATTRIBUTE_REFERRER);
|
|
||||||
log.debug("returning to referrer: " + referrer);
|
|
||||||
if (referrer == null) {
|
|
||||||
referrer = figureHomePageUrl(req);
|
|
||||||
log.debug("returning to home page: " + referrer);
|
|
||||||
}
|
|
||||||
|
|
||||||
req.getSession().removeAttribute(ATTRIBUTE_REFERRER);
|
|
||||||
resp.sendRedirect(referrer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String figureHomePageUrl(HttpServletRequest req) {
|
|
||||||
StringBuffer url = req.getRequestURL();
|
|
||||||
String uri = req.getRequestURI();
|
|
||||||
int authLength = url.length() - uri.length();
|
|
||||||
String auth = url.substring(0, authLength);
|
|
||||||
return auth + req.getContextPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Authenticator getAuthenticator(HttpServletRequest req) {
|
|
||||||
return Authenticator.getInstance(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dumpRequestHeaders(HttpServletRequest req) {
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Enumeration<String> names = req.getHeaderNames();
|
|
||||||
while (names.hasMoreElements()) {
|
|
||||||
String name = names.nextElement();
|
|
||||||
log.debug("header: " + name + "=" + req.getHeader(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(HttpServletRequest request,
|
|
||||||
HttpServletResponse response) throws ServletException, IOException {
|
|
||||||
doPost(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
||||||
|
|
||||||
|
import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginShibbolethSetup.ATTRIBUTE_REFERRER;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the return from the Shibboleth login server. If we are successful,
|
||||||
|
* record the login. Otherwise, display the failure.
|
||||||
|
*/
|
||||||
|
public class LoginShibbolethReturn extends BaseLoginServlet {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LoginShibbolethReturn.class);
|
||||||
|
|
||||||
|
/** The configuration property that tells what provider name we expect. */
|
||||||
|
private static final String PROPERTY_SHIBBOLETH_PROVIDER = "shibboleth.provider";
|
||||||
|
|
||||||
|
/** On return froma Shibboleth login, this header holds the provider name. */
|
||||||
|
private static final String HEADING_SHIBBOLETH_PROVIDER = "shib-identity-provider";
|
||||||
|
|
||||||
|
/** On return froma Shibboleth login, this header holds the user name. */
|
||||||
|
private static final String HEADING_SHIBBOLETH_USERNAME = "glid";
|
||||||
|
|
||||||
|
private static final Message MESSAGE_LOGIN_FAILED = new LoginProcessBean.Message(
|
||||||
|
"Shibboleth login failed.", LoginProcessBean.MLevel.ERROR);
|
||||||
|
|
||||||
|
private static final Message MESSAGE_NO_SUCH_USER = new LoginProcessBean.Message(
|
||||||
|
"Shibboleth login succeeded, but user {0} is unknown to VIVO.",
|
||||||
|
LoginProcessBean.MLevel.ERROR);
|
||||||
|
|
||||||
|
private static final Message MESSAGE_NO_SHIBBOLETH_PROVIDER = new LoginProcessBean.Message(
|
||||||
|
"deploy.properties doesn't contain a value for '"
|
||||||
|
+ PROPERTY_SHIBBOLETH_PROVIDER + "'",
|
||||||
|
LoginProcessBean.MLevel.ERROR);
|
||||||
|
|
||||||
|
private final LoginRedirector loginRedirector = new LoginRedirector();
|
||||||
|
private String shibbolethProvider;
|
||||||
|
|
||||||
|
/** Get the configuration properties. */
|
||||||
|
@Override
|
||||||
|
public void init() throws ServletException {
|
||||||
|
shibbolethProvider = ConfigurationProperties
|
||||||
|
.getProperty(PROPERTY_SHIBBOLETH_PROVIDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returning from the Shibboleth server. If we were successful, the headers
|
||||||
|
* will contain the Shibboleth provider name and the name of the user who
|
||||||
|
* just logged in.
|
||||||
|
*
|
||||||
|
* We report problems if the provider name is missing or we don't know the
|
||||||
|
* correct value for it. We also report problems if the username is missing
|
||||||
|
* or if we don't recognize that user.
|
||||||
|
*
|
||||||
|
* If there are no problems, record the login and redirect like we would on
|
||||||
|
* a normal login.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
String provider = req.getHeader(HEADING_SHIBBOLETH_PROVIDER);
|
||||||
|
String user = req.getHeader(HEADING_SHIBBOLETH_USERNAME);
|
||||||
|
log.debug("Info from Shibboleth: user=" + user + ", provider="
|
||||||
|
+ provider);
|
||||||
|
|
||||||
|
if ((provider == null) || (user == null)) {
|
||||||
|
complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER,
|
||||||
|
MESSAGE_LOGIN_FAILED);
|
||||||
|
} else if (shibbolethProvider == null) {
|
||||||
|
log.debug("No shibboleth provider in deploy.properties");
|
||||||
|
complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER,
|
||||||
|
MESSAGE_NO_SHIBBOLETH_PROVIDER);
|
||||||
|
} else if (!this.shibbolethProvider.equals(provider)) {
|
||||||
|
log.error("Wrong shibboleth provider: " + provider);
|
||||||
|
complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER,
|
||||||
|
MESSAGE_LOGIN_FAILED);
|
||||||
|
} else if (!getAuthenticator(req).isExistingUser(user)) {
|
||||||
|
log.debug("No such user: " + user);
|
||||||
|
complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER,
|
||||||
|
MESSAGE_NO_SUCH_USER, user);
|
||||||
|
} else {
|
||||||
|
log.debug("Logging in as " + user);
|
||||||
|
recordLoginAndRedirect(req, resp, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Success. Record the login and send them to the appropriate page. */
|
||||||
|
private void recordLoginAndRedirect(HttpServletRequest req,
|
||||||
|
HttpServletResponse resp, String username)
|
||||||
|
throws UnsupportedEncodingException, IOException {
|
||||||
|
getAuthenticator(req).recordUserIsLoggedIn(username);
|
||||||
|
LoginProcessBean.removeBean(req);
|
||||||
|
req.getSession().removeAttribute(ATTRIBUTE_REFERRER);
|
||||||
|
loginRedirector.redirectLoggedInUser(req, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request,
|
||||||
|
HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doPost(request, response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the Shibboleth login process.
|
||||||
|
*
|
||||||
|
* Write down the page that triggered the request, so we can get back to it.
|
||||||
|
*
|
||||||
|
* Send a request to the Shibboleth server that will return us to the
|
||||||
|
* LoginShibbolethReturn servlet for further processing.
|
||||||
|
*/
|
||||||
|
public class LoginShibbolethSetup extends BaseLoginServlet {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(LoginShibbolethSetup.class);
|
||||||
|
|
||||||
|
/** This session attribute tells where we came from. */
|
||||||
|
static final String ATTRIBUTE_REFERRER = LoginShibbolethSetup.class
|
||||||
|
.getName() + ".referrer";
|
||||||
|
|
||||||
|
private static final String RETURN_SERVLET_URL = "/loginShibbolethReturn";
|
||||||
|
|
||||||
|
/** This http header holds the referring page. */
|
||||||
|
private static final String HEADING_REFERRER = "referer";
|
||||||
|
|
||||||
|
/** The configuration property that points to the Shibboleth server. */
|
||||||
|
private static final String PROPERTY_SHIBBOLETH_SERVER_URL = "shibboleth.server.url";
|
||||||
|
|
||||||
|
/** The complaint we make if there is no Shibbolet server property. */
|
||||||
|
private static final Message MESSAGE_NO_SHIBBOLETH_SERVER = new LoginProcessBean.Message(
|
||||||
|
"deploy.properties doesn't contain a value for '"
|
||||||
|
+ PROPERTY_SHIBBOLETH_SERVER_URL + "'",
|
||||||
|
LoginProcessBean.MLevel.ERROR);
|
||||||
|
|
||||||
|
private String shibbolethServerUrl;
|
||||||
|
|
||||||
|
/** Get the configuration property. */
|
||||||
|
@Override
|
||||||
|
public void init() throws ServletException {
|
||||||
|
shibbolethServerUrl = ConfigurationProperties
|
||||||
|
.getProperty(PROPERTY_SHIBBOLETH_SERVER_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write down the referring page, record that we are logging in, and
|
||||||
|
* redirect to the shib server URL.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
// Record where we came from, so we can get back there.
|
||||||
|
storeTheReferringPage(req);
|
||||||
|
|
||||||
|
// If we have no URL for the Shibboleth server, give up.
|
||||||
|
if (shibbolethServerUrl == null) {
|
||||||
|
log.debug("No shibboleth server in deploy.properties");
|
||||||
|
complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER,
|
||||||
|
MESSAGE_NO_SHIBBOLETH_SERVER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record that we are in the process of logging in.
|
||||||
|
LoginProcessBean.getBean(req).setState(
|
||||||
|
LoginProcessBean.State.LOGGING_IN);
|
||||||
|
|
||||||
|
// Hand over to Shibboleth.
|
||||||
|
log.debug("Sending to shibboleth server.");
|
||||||
|
resp.sendRedirect(buildShibbolethRedirectUrl(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remember where we came from - we'll need to go back there. */
|
||||||
|
private void storeTheReferringPage(HttpServletRequest req) {
|
||||||
|
String referrer = req.getHeader(HEADING_REFERRER);
|
||||||
|
if (referrer == null) {
|
||||||
|
dumpRequestHeaders(req);
|
||||||
|
referrer = figureHomePageUrl(req);
|
||||||
|
}
|
||||||
|
log.debug("Referring page is '" + referrer + "'");
|
||||||
|
req.getSession().setAttribute(ATTRIBUTE_REFERRER, referrer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** How do we get to the Shibboleth server and back? */
|
||||||
|
private String buildShibbolethRedirectUrl(HttpServletRequest req) {
|
||||||
|
try {
|
||||||
|
String returnUrl = figureHomePageUrl(req) + RETURN_SERVLET_URL;
|
||||||
|
String encodedReturnUrl = URLEncoder.encode(returnUrl, "UTF-8");
|
||||||
|
String shibbolethUrl = shibbolethServerUrl + "?target="
|
||||||
|
+ encodedReturnUrl;
|
||||||
|
log.debug("shibbolethURL is '" + shibbolethUrl + "'");
|
||||||
|
return shibbolethUrl;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e); // No UTF-8? Really?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dumpRequestHeaders(HttpServletRequest req) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Enumeration<String> names = req.getHeaderNames();
|
||||||
|
while (names.hasMoreElements()) {
|
||||||
|
String name = names.nextElement();
|
||||||
|
log.debug("header: " + name + "=" + req.getHeader(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request,
|
||||||
|
HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doPost(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue