/* [The "BSD licence"] Copyright (c) 2003 Terence Parr, jGuru.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.pageforge.service; import org.pageforge.*; import org.pageforge.support.*; import org.pageforge.support.Utils; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.Cookie; public class SessionService { private static SessionService _instance; /** Get a singleton instance. Not incredibly useful here as everything * is static data. */ public static synchronized SessionService instance() { if(_instance == null) { _instance = new SessionService(); } return _instance; } /** Indicates they want to autologin to site */ public static final String COOKIE_AUTOLOGIN = "auto_login"; /** This code is matched up via UserServiceInterface.getUniqueHash() * to know who to autologin. */ public static final String COOKIE_HASH = "unique_id"; /** Indicates session has been initialized. */ public static final String SESSION_INIT = "init"; /** Session variable pointing to a user object */ public static final String SESSION_MEMBER = "user"; /** Indicates currently logged in */ public static final String SESSION_LOGGEDIN = "loggedin"; public UserInterface getUser(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws Exception { if ( sessionIsInitialized(session) ) { return (UserInterface)session.getValue(SESSION_MEMBER); } // else session was *not* initialized // try to auto log them in autologin(request, response, session); // we either successfully autologged them in or they are // a guest; either way jguru_MemberContext is set return (UserInterface)session.getValue(SESSION_MEMBER); } /** Attempt an autologin. The person's unique hash must match * a record in our ENTP Person table. Return true if routine * succeeds in autologging in that person. Do a guest login * if autologin fails; i.e., session is always initialized * after this routine. */ public boolean autologin(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception { String autologin = getCookieValue(request, COOKIE_AUTOLOGIN); // If they want to be autologged in but they have not yet logged in // try to log them in. if ( autologin!=null && autologin.equals("true") && !userIsLoggedIn(session) ) { // Get the unique key that identifies a user String hash = getCookieValue(request, COOKIE_HASH); if ( login(request, response, session, hash) ) { return true; } } return false; } /** Manual login via email/passwd */ public boolean login(HttpServletRequest request, HttpServletResponse response, HttpSession session, String email, String passwd) throws Exception { UserInterface user = PageDispatcher.getApplication().getUserByLogin(email); if( user==null || user.getPassword()==null ) { return false; } // check password if ( !user.getPassword().equals(passwd) ) { return false; } login(request, response, session, user); return true; } /** Log somebody in from unique hash (part of autologin) */ private boolean login(HttpServletRequest request, HttpServletResponse response, HttpSession session, String uniquehash) throws Exception { UserInterface user = PageDispatcher.getApplication().getUserByUniqueHash(uniquehash); if ( user==null ) { return false; } login(request, response, session, user); return true; } /** Once a user record is available, do the actual login junk; user * is autologged in from now on */ public void login(HttpServletRequest request, HttpServletResponse response, HttpSession session, UserInterface user) throws Exception { String uniqueHash = user.getUniqueHash(); if ( uniqueHash==null ) { // ignore, can't autolog in anybody w/o a unique hash return; } setCookieValue(response, COOKIE_HASH, uniqueHash); setCookieValue(response, COOKIE_AUTOLOGIN, "true"); // not seen before; must create put in session startMemberSession(session, user); } /** If we've seen this session before, we've set "logged in" * regardless of user/guest status. */ public boolean sessionIsInitialized(HttpSession session) { String loggedIn = (String) session.getValue(SESSION_LOGGEDIN); return loggedIn!=null; } /** The current user wants to log out; wack session and turn off * auto login */ public void logout(HttpServletRequest request, HttpServletResponse response, HttpSession session) { stopSession(session); killAutoLoginCookie(response); System.out.println("logging out"); } // S E S S I O N S T U F F /** For guests, SESSION_LOGGEDIN is false, but must exist lest * we think the session has not been initialized */ private void startGuestSession(HttpSession session, UserInterface user) { session.putValue(SESSION_LOGGEDIN, "false"); session.putValue(SESSION_MEMBER, user); } private static void stopSession(HttpSession session) { session.removeValue(SESSION_LOGGEDIN); session.removeValue(SESSION_MEMBER); session.invalidate(); } /** SESSION_LOGGEDIN must be true if this person is logged in. */ private void startMemberSession(HttpSession session, UserInterface user) { session.putValue(SESSION_LOGGEDIN, "true"); session.putValue(SESSION_MEMBER, user); } public String computeUniqueHash(String email, String password) { // Compute a unique hash code for this person's account // Based upon when they register, their login, their password String message = email + password + System.currentTimeMillis(); return Utils.computeHash(message); } public boolean userIsLoggedIn(HttpSession session) { String loggedIn = (String) session.getValue(SESSION_LOGGEDIN); if ( loggedIn!=null && loggedIn.equals("true") ) { return true; } return false; } // C O O K I E S T U F F /** Find a cookie by name; return first found */ public static Cookie getCookie(HttpServletRequest request, String name) { Cookie[] allCookies; if ( name==null ) { throw new IllegalArgumentException("cookie name is null"); } allCookies = request.getCookies(); if (allCookies != null) { for (int i=0; i < allCookies.length; i++) { Cookie candidate = allCookies[i]; if (name.equals(candidate.getName()) ) { return candidate; } } } return null; } /** Find a cookie by name; return first found */ public static String getCookieValue(HttpServletRequest request, String name) { Cookie c = getCookie(request, name); if ( c!=null ) { return c.getValue(); } return null; } /** Set a cookie by name */ public static void setCookieValue(HttpServletResponse response, String name, String value) { Cookie c = new Cookie(name,value); c.setMaxAge( 3 * 30 * 24 * 60 * 60 ); c.setPath( "/" ); response.addCookie( c ); } private void killAutoLoginCookie(HttpServletResponse response) { Cookie c = new Cookie(COOKIE_AUTOLOGIN,"false"); c.setMaxAge( 0 ); // An age of 0 is defined to mean "delete cookie" c.setPath( "/" ); response.addCookie( c ); } }