/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.app.webui.util; import java.io.IOException; import java.sql.SQLException; import java.util.Iterator; import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.jsp.jstl.core.Config; import org.apache.log4j.Logger; import org.dspace.authenticate.AuthenticationManager; import org.dspace.authenticate.AuthenticationMethod; import org.dspace.authorize.AuthorizeManager; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.core.ConfigurationManager; import org.dspace.eperson.EPerson; /** * Methods for authenticating the user. This is DSpace platform code, as opposed * to the site-specific authentication code, that resides in implementations of * the <code>org.dspace.eperson.AuthenticationMethod</code> interface. * * @author Robert Tansley * @version $Revision$ */ public class Authenticate { /** log4j category */ private static Logger log = Logger.getLogger(Authenticate.class); /** * Return the request that the system should be dealing with, given the * request that the browse just sent. If the incoming request is from a * redirect resulting from successful authentication, a request object * corresponding to the original request that prompted authentication is * returned. Otherwise, the request passed in is returned. * * @param request * the incoming HTTP request * @return the HTTP request the DSpace system should deal with */ public static HttpServletRequest getRealRequest(HttpServletRequest request) { HttpSession session = request.getSession(); if (session.getAttribute("resuming.request") != null) { // Get info about the interrupted request RequestInfo requestInfo = (RequestInfo) session .getAttribute("interrupted.request.info"); HttpServletRequest actualRequest; if (requestInfo == null) { // Can't find the wrapped request information. // FIXME: Proceed with current request - correct? actualRequest = request; } else { /* * Wrap the current request to make it look like the interruped * one */ actualRequest = requestInfo.wrapRequest(request); } // Remove the info from the session so it isn't resumed twice session.removeAttribute("resuming.request"); session.removeAttribute("interrupted.request.info"); session.removeAttribute("interrupted.request.url"); // Return the wrapped request return actualRequest; } else { return request; } } /** * Resume a previously interrupted request. This is invoked when a user has * been successfully authenticated. The request which led to authentication * will be resumed. * * @param request * <em>current</em> HTTP request * @param response * HTTP response */ public static void resumeInterruptedRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); String originalURL = (String) session .getAttribute("interrupted.request.url"); if (originalURL == null) { // If for some reason we don't have the original URL, redirect // to My DSpace originalURL = request.getContextPath() + "/mydspace"; } else { // Set the flag in the session, so that when the redirect is // followed, we'll know to resume the interrupted request session.setAttribute("resuming.request", Boolean.TRUE); } // Send the redirect response.sendRedirect(response.encodeRedirectURL(originalURL)); } /** * Start the authentication process. This packages up the request that led * to authentication being required, and then invokes the site-specific * authentication method. * * If it returns true, the user was authenticated without any * redirection (e.g. by an X.509 certificate or other implicit method) so * the process that called this can continue and send its own response. * A "false" result means this method has sent its own redirect. * * @param context * current DSpace context * @param request * current HTTP request - the one that prompted authentication * @param response * current HTTP response * * @return true if authentication is already finished (implicit method) */ public static boolean startAuthentication(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); /* * Authenticate: * 1. try implicit methods first, since that may work without * a redirect. return true if no redirect needed. * 2. if those fail, redirect to enter credentials. * return false. */ if (AuthenticationManager.authenticateImplicit(context, null, null, null, request) == AuthenticationMethod.SUCCESS) { loggedIn(context, request, context.getCurrentUser()); log.info(LogManager.getHeader(context, "login", "type=implicit")); if(context.getCurrentUser() != null){ //We have a new user Authenticate.resumeInterruptedRequest(request, response); return false; }else{ //Couldn't log & authentication finished return true; } } else { // Since we may be doing a redirect, make sure the redirect is not // cached response.addDateHeader("expires", 1); response.addHeader("Pragma", "no-cache"); response.addHeader("Cache-control", "no-store"); // Store the data from the request that led to authentication RequestInfo info = new RequestInfo(request); session.setAttribute("interrupted.request.info", info); // Store the URL of the request that led to authentication session.setAttribute("interrupted.request.url", UIUtil .getOriginalURL(request)); /* * Grovel over authentication methods, counting the * ones with a "redirect" login page -- if there's only one, * go directly there. If there is a choice, go to JSP chooser. */ Iterator ai = AuthenticationManager.authenticationMethodIterator(); AuthenticationMethod am; int count = 0; String url = null; while (ai.hasNext()) { String s; am = (AuthenticationMethod)ai.next(); s = am.loginPageURL(context, request, response); if (s != null) { url = s; ++count; } } if (count == 1) { response.sendRedirect(url); } else { JSPManager.showJSP(request, response, "/login/chooser.jsp"); } } return false; } /** * Store information about the current user in the request and context * * @param context * DSpace context * @param request * HTTP request * @param eperson * the eperson logged in */ public static void loggedIn(Context context, HttpServletRequest request, EPerson eperson) { HttpSession session = request.getSession(); // For security reasons after login, give the user a new session if ((!session.isNew()) && (session.getAttribute("dspace.current.user.id") == null)) { // Keep the user's locale setting if set Locale sessionLocale = UIUtil.getSessionLocale(request); // Get info about the interrupted request, if set RequestInfo requestInfo = (RequestInfo) session.getAttribute("interrupted.request.info"); // Get the original URL of interrupted request, if set String requestUrl = (String) session.getAttribute("interrupted.request.url"); // Invalidate session unless dspace.cfg says not to if(ConfigurationManager.getBooleanProperty("webui.session.invalidate", true)) { session.invalidate(); } // Give the user a new session session = request.getSession(); // Restore the session locale if (sessionLocale != null) { Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale); } // Restore interrupted request information and url to new session if (requestInfo != null && requestUrl != null) { session.setAttribute("interrupted.request.info", requestInfo); session.setAttribute("interrupted.request.url", requestUrl); } } context.setCurrentUser(eperson); boolean isAdmin = false; try { isAdmin = AuthorizeManager.isAdmin(context); } catch (SQLException se) { log.warn("Unable to use AuthorizeManager " + se); } finally { request.setAttribute("is.admin", Boolean.valueOf(isAdmin)); } // We store the current user in the request as an EPerson object... request.setAttribute("dspace.current.user", eperson); // and in the session as an ID session.setAttribute("dspace.current.user.id", Integer.valueOf(eperson.getID())); // and the remote IP address to compare against later requests // so we can detect session hijacking. session.setAttribute("dspace.current.remote.addr", request.getRemoteAddr()); } /** * Log the user out * * @param context * DSpace context * @param request * HTTP request */ public static void loggedOut(Context context, HttpServletRequest request) { HttpSession session = request.getSession(); context.setCurrentUser(null); request.removeAttribute("is.admin"); request.removeAttribute("dspace.current.user"); session.removeAttribute("dspace.current.user.id"); // Keep the user's locale setting if set Locale sessionLocale = UIUtil.getSessionLocale(request); // Invalidate session unless dspace.cfg says not to if(ConfigurationManager.getBooleanProperty("webui.session.invalidate", true)) { session.invalidate(); } // Restore the session locale if (sessionLocale != null) { Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale); } } }