001: /*
002: * Authenticate.java
003: *
004: * Version: $Revision: 2168 $
005: *
006: * Date: $Date: 2007-08-27 17:40:09 -0500 (Mon, 27 Aug 2007) $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.app.webui.util;
041:
042: import java.io.IOException;
043: import java.sql.SQLException;
044: import java.util.Iterator;
045:
046: import javax.servlet.ServletException;
047: import javax.servlet.http.HttpServletRequest;
048: import javax.servlet.http.HttpServletResponse;
049: import javax.servlet.http.HttpSession;
050:
051: import org.apache.log4j.Logger;
052: import org.dspace.authenticate.AuthenticationManager;
053: import org.dspace.authenticate.AuthenticationMethod;
054: import org.dspace.authorize.AuthorizeManager;
055: import org.dspace.core.Context;
056: import org.dspace.core.LogManager;
057: import org.dspace.eperson.EPerson;
058:
059: /**
060: * Methods for authenticating the user. This is DSpace platform code, as opposed
061: * to the site-specific authentication code, that resides in implementations of
062: * the <code>org.dspace.eperson.AuthenticationMethod</code> interface.
063: *
064: * @author Robert Tansley
065: * @version $Revision: 2168 $
066: */
067: public class Authenticate {
068: /** log4j category */
069: private static Logger log = Logger.getLogger(Authenticate.class);
070:
071: /**
072: * Return the request that the system should be dealing with, given the
073: * request that the browse just sent. If the incoming request is from a
074: * redirect resulting from successful authentication, a request object
075: * corresponding to the original request that prompted authentication is
076: * returned. Otherwise, the request passed in is returned.
077: *
078: * @param request
079: * the incoming HTTP request
080: * @return the HTTP request the DSpace system should deal with
081: */
082: public static HttpServletRequest getRealRequest(
083: HttpServletRequest request) {
084: HttpSession session = request.getSession();
085:
086: if (session.getAttribute("resuming.request") != null) {
087: // Get info about the interrupted request
088: RequestInfo requestInfo = (RequestInfo) session
089: .getAttribute("interrupted.request.info");
090:
091: HttpServletRequest actualRequest;
092:
093: if (requestInfo == null) {
094: // Can't find the wrapped request information.
095: // FIXME: Proceed with current request - correct?
096: actualRequest = request;
097: } else {
098: /*
099: * Wrap the current request to make it look like the interruped
100: * one
101: */
102: actualRequest = requestInfo.wrapRequest(request);
103: }
104:
105: // Remove the info from the session so it isn't resumed twice
106: session.removeAttribute("resuming.request");
107: session.removeAttribute("interrupted.request.info");
108: session.removeAttribute("interrupted.request.url");
109:
110: // Return the wrapped request
111: return actualRequest;
112: } else {
113: return request;
114: }
115: }
116:
117: /**
118: * Resume a previously interrupted request. This is invoked when a user has
119: * been successfully authenticated. The request which led to authentication
120: * will be resumed.
121: *
122: * @param request
123: * <em>current</em> HTTP request
124: * @param response
125: * HTTP response
126: */
127: public static void resumeInterruptedRequest(
128: HttpServletRequest request, HttpServletResponse response)
129: throws IOException {
130: HttpSession session = request.getSession();
131: String originalURL = (String) session
132: .getAttribute("interrupted.request.url");
133:
134: if (originalURL == null) {
135: // If for some reason we don't have the original URL, redirect
136: // to My DSpace
137: originalURL = request.getContextPath() + "/mydspace";
138: } else {
139: // Set the flag in the session, so that when the redirect is
140: // followed, we'll know to resume the interrupted request
141: session.setAttribute("resuming.request", new Boolean(true));
142: }
143:
144: // Send the redirect
145: response.sendRedirect(response.encodeRedirectURL(originalURL));
146: }
147:
148: /**
149: * Start the authentication process. This packages up the request that led
150: * to authentication being required, and then invokes the site-specific
151: * authentication method.
152: *
153: * If it returns true, the user was authenticated without any
154: * redirection (e.g. by an X.509 certificate or other implicit method) so
155: * the process that called this can continue and send its own response.
156: * A "false" result means this method has sent its own redirect.
157: *
158: * @param context
159: * current DSpace context
160: * @param request
161: * current HTTP request - the one that prompted authentication
162: * @param response
163: * current HTTP response
164: *
165: * @return true if authentication is already finished (implicit method)
166: */
167: public static boolean startAuthentication(Context context,
168: HttpServletRequest request, HttpServletResponse response)
169: throws ServletException, IOException {
170: HttpSession session = request.getSession();
171:
172: /*
173: * Authenticate:
174: * 1. try implicit methods first, since that may work without
175: * a redirect. return true if no redirect needed.
176: * 2. if those fail, redirect to enter credentials.
177: * return false.
178: */
179: if (AuthenticationManager.authenticateImplicit(context, null,
180: null, null, request) == AuthenticationMethod.SUCCESS) {
181: loggedIn(context, request, context.getCurrentUser());
182: log.info(LogManager.getHeader(context, "login",
183: "type=implicit"));
184: return true;
185: } else {
186: // Since we may be doing a redirect, make sure the redirect is not
187: // cached
188: response.addDateHeader("expires", 1);
189: response.addHeader("Pragma", "no-cache");
190: response.addHeader("Cache-control", "no-store");
191:
192: // Store the data from the request that led to authentication
193: RequestInfo info = new RequestInfo(request);
194: session.setAttribute("interrupted.request.info", info);
195:
196: // Store the URL of the request that led to authentication
197: session.setAttribute("interrupted.request.url", UIUtil
198: .getOriginalURL(request));
199:
200: /*
201: * Grovel over authentication methods, counting the
202: * ones with a "redirect" login page -- if there's only one,
203: * go directly there. If there is a choice, go to JSP chooser.
204: */
205: Iterator ai = AuthenticationManager
206: .authenticationMethodIterator();
207: AuthenticationMethod am;
208: int count = 0;
209: String url = null;
210: while (ai.hasNext()) {
211: String s;
212: am = (AuthenticationMethod) ai.next();
213: if ((s = am.loginPageURL(context, request, response)) != null) {
214: url = s;
215: ++count;
216: }
217: }
218: if (count == 1)
219: response.sendRedirect(url);
220: else
221: JSPManager.showJSP(request, response,
222: "/login/chooser.jsp");
223: }
224: return false;
225: }
226:
227: /**
228: * Store information about the current user in the request and context
229: *
230: * @param context
231: * DSpace context
232: * @param request
233: * HTTP request
234: * @param eperson
235: * the eperson logged in
236: */
237: public static void loggedIn(Context context,
238: HttpServletRequest request, EPerson eperson) {
239: HttpSession session = request.getSession();
240:
241: context.setCurrentUser(eperson);
242:
243: boolean isAdmin = false;
244:
245: try {
246: isAdmin = AuthorizeManager.isAdmin(context);
247: } catch (SQLException se) {
248: log.warn("Unable to use AuthorizeManager " + se);
249: } finally {
250: request.setAttribute("is.admin", new Boolean(isAdmin));
251: }
252:
253: // We store the current user in the request as an EPerson object...
254: request.setAttribute("dspace.current.user", eperson);
255:
256: // and in the session as an ID
257: session.setAttribute("dspace.current.user.id", new Integer(
258: eperson.getID()));
259:
260: // and the remote IP address to compare against later requests
261: // so we can detect session hijacking.
262: session.setAttribute("dspace.current.remote.addr", request
263: .getRemoteAddr());
264:
265: }
266:
267: /**
268: * Log the user out
269: *
270: * @param context
271: * DSpace context
272: * @param request
273: * HTTP request
274: */
275: public static void loggedOut(Context context,
276: HttpServletRequest request) {
277: HttpSession session = request.getSession();
278:
279: context.setCurrentUser(null);
280: request.removeAttribute("is.admin");
281: request.removeAttribute("dspace.current.user");
282: session.removeAttribute("dspace.current.user.id");
283: }
284: }
|