|
What this is
Other links
The source code/* * $Header: /cvsroot/mvnforum/mvnforum/src/com/mvnforum/auth/OnlineUserManager.java,v 1.26.2.1 2005/06/17 17:49:29 minhnn Exp $ * $Author: minhnn $ * $Revision: 1.26.2.1 $ * $Date: 2005/06/17 17:49:29 $ * * ==================================================================== * * Copyright (C) 2002-2005 by MyVietnam.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * All copyright notices regarding mvnForum MUST remain intact * in the scripts and in the outputted HTML. * The "powered by" text/logo with a link back to * http://www.mvnForum.com and http://www.MyVietnam.net in the * footer of the pages MUST remain visible when the pages * are viewed on the internet or intranet. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Support can be obtained from support forums at: * http://www.mvnForum.com/mvnforum/index * * Correspondence and Marketing Questions can be sent to: * info@MyVietnam.net * * @author: Minh Nguyen minhnn@MyVietnam.net * @author: Mai Nguyen mai.nh@MyVietnam.net */ package com.mvnforum.auth; import java.sql.Timestamp; import java.util.*; import javax.servlet.http.*; import com.mvnforum.*; import com.mvnforum.db.DAOFactory; import net.myvietnam.mvncore.exception.*; import net.myvietnam.mvncore.security.Encoder; import net.myvietnam.mvncore.security.FloodControl; import net.myvietnam.mvncore.util.*; public class OnlineUserManager { private static final int REMOVE_INTERVAL = 2000; //update every 2 second private static final String MVNFORUM_SESSION_USERNAME = "mvnforum.membername"; private static final String MVNFORUM_SESSION_PASSWORD = "mvnforum.encodedpassword"; private static final String MVNFORUM_COOKIE_USERNAME = "mvnforum.membername"; private static final String MVNFORUM_COOKIE_PASSWORD = "mvnforum.encodedpassword"; private static final String MVNFORUM_COOKIE_PATH = "/"; public static final String PASSWORD_OF_METHOD_REALM = "Realm"; public static final String PASSWORD_OF_METHOD_CUSTOMIZATION = "Remote"; //static variable private static OnlineUserManager instance = new OnlineUserManager(); //instance variable private Map userMap = new TreeMap(); private long timeOfLastRemoveAction = 0; private transient Vector onlineUserListeners; private Authenticator authenticator = null; private OnlineUserManager() { } public static OnlineUserManager getInstance() { return instance; } public Authenticator getAuthenticator() { return authenticator; } public void setAuthenticator(Authenticator authenticator) { this.authenticator = authenticator; } /** * MemberUtil method to be called from Processor. * It assumes that to input parameters are * MemberName for username * MemberMatkhau for password */ public void processLogin(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, AssertionException, DatabaseException, BadInputException, FloodException { String memberName = ParamUtil.getParameter(request, "MemberName", true); StringUtil.checkGoodName(memberName);// check for better security String memberPassword = ""; String memberPasswordMD5 = ParamUtil.getParameter(request, "md5pw", false); if (memberPasswordMD5.length() == 0 || (memberPasswordMD5.endsWith("==") == false)) { // md5 is not valid, try to use unencoded password method memberPassword = ParamUtil.getParameterPassword(request, "MemberMatkhau", 3, 0); } String currentIP = request.getRemoteAddr(); try { // Control the login action, we dont want user to try too many login attempt FloodControl.ensureNotReachMaximum(MVNForumGlobal.FLOOD_ID_LOGIN, currentIP); OnlineUser user = null; if (memberPassword.length() > 0) { // that is we cannot find the md5 password user = login(request, response, memberName, memberPassword, false); } else { // have the md5, go ahead user = login(request, response, memberName, memberPasswordMD5, true); } ((OnlineUserImpl)user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_HTML_FORM); } catch (AuthenticationException ex) { // only increase login count if unsucessful FloodControl.increaseCount(MVNForumGlobal.FLOOD_ID_LOGIN, currentIP); if (ex.getReason() == NotLoginException.WRONG_PASSWORD) { request.setAttribute("MemberName", memberName);// so user dont have to retype USER NAME } throw ex; } catch (FloodException fe) { Locale locale = I18nUtil.getLocaleInRequest(request); Integer maxWrongLogins = new Integer(FloodControl.getActionsPerHour(MVNForumGlobal.FLOOD_ID_LOGIN)); //throw new FloodException("You have reached the maximum number of wrong login actions for this page. Please try this page later. This is to prevent forum from being flooded."); String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.FloodException.login_too_many_times", new Object[]{ maxWrongLogins }); throw new FloodException(localizedMessage); } } /** * NOTE: This method MUST be the only way to authenticate a user * NOTE: the parameter response can be equals null */ protected OnlineUser login(HttpServletRequest request, HttpServletResponse response, String memberName, String memberPassword, boolean passwordEncoded) throws AuthenticationException, DatabaseException, AssertionException { try { StringUtil.checkGoodName(memberName); } catch (Exception ex) { throw new AuthenticationException(ex.getMessage(), NotLoginException.WRONG_NAME); } String encodedPassword; OnlineUser user; if (passwordEncoded) { encodedPassword = memberPassword; user = ManagerFactory.getOnlineUserFactory().getAuthenticatedUser(request, response, memberName, encodedPassword, true); } else { encodedPassword = ManagerFactory.getOnlineUserFactory().getEncodedPassword(memberName, memberPassword); //user = ManagerFactory.getOnlineUserFactory().getAuthenticatedUser(request, response, memberName, memberPassword, false); user = ManagerFactory.getOnlineUserFactory().getAuthenticatedUser(request, response, memberName, encodedPassword, true); } HttpSession session = request.getSession(); String sessionID = session.getId(); setOnlineUser(sessionID, user); // now save the login info in the session only if we support // encoded passwords if (null != encodedPassword) { session.setAttribute(MVNFORUM_SESSION_USERNAME, memberName); session.setAttribute(MVNFORUM_SESSION_PASSWORD, encodedPassword); } boolean fromLoginPage = ParamUtil.getParameterBoolean(request, "FromLoginPage"); if ( fromLoginPage && (response != null) ) { manageAutoLogin(memberName, encodedPassword, request, response); } // Now call the postLogin method, in the default implementation, the default folder // is checked and created if not existed ManagerFactory.getOnlineUserFactory().postLogin(request, response, user); return user; } protected void manageAutoLogin(String memberName, String encodedPassword, HttpServletRequest request, HttpServletResponse response) { boolean autoLogin = ParamUtil.getParameterBoolean(request, "AutoLogin"); if (autoLogin) { int autoLoginExpire = (60 * 60 * 24) * 1; // 1 day try { autoLoginExpire = ParamUtil.getParameterInt(request, "AutoLoginExpire"); } catch (Exception ex) { // do nothing } Cookie nameCookie = new Cookie(MVNFORUM_COOKIE_USERNAME, Encoder.encodeURL(memberName)); nameCookie.setMaxAge(autoLoginExpire); nameCookie.setPath(MVNFORUM_COOKIE_PATH); Cookie passwordCookie = new Cookie(MVNFORUM_COOKIE_PASSWORD, encodedPassword); passwordCookie.setMaxAge(autoLoginExpire); passwordCookie.setPath(MVNFORUM_COOKIE_PATH); response.addCookie(nameCookie); response.addCookie(passwordCookie); } } public void logout(HttpServletRequest request, HttpServletResponse response) throws DatabaseException, AssertionException, AuthenticationException { HttpSession session = request.getSession(); String sessionID = session.getId(); OnlineUser oldUser = getOnlineUser(request); String cssPath = oldUser.getCssPath(); String logoPath = oldUser.getLogoPath(); OnlineUser user = null; if (authenticator == null) { // temporary hack, if no authenticator has been set, // then we use the old method // @todo: more thought on this later user = ManagerFactory.getOnlineUserFactory().getAnonymousUser(request); user.setCssPath(cssPath); user.setLogoPath(logoPath); } setOnlineUser(sessionID, user); ManagerFactory.getOnlineUserFactory().logout(request, response); // now always clear the session information session.setAttribute(MVNFORUM_SESSION_USERNAME, null); session.setAttribute(MVNFORUM_SESSION_PASSWORD, null); } public void deleteCookie(HttpServletRequest request, HttpServletResponse response) { Cookie nameCookie = new Cookie(MVNFORUM_COOKIE_USERNAME, ""); nameCookie.setPath(MVNFORUM_COOKIE_PATH); nameCookie.setMaxAge(0);// delete this cookie Cookie passwordCookie = new Cookie(MVNFORUM_COOKIE_PASSWORD, ""); passwordCookie.setPath(MVNFORUM_COOKIE_PATH); passwordCookie.setMaxAge(0);// delete this cookie response.addCookie(nameCookie); response.addCookie(passwordCookie); } public OnlineUser getOnlineUser(HttpServletRequest request) throws AuthenticationException, AssertionException, DatabaseException { long currentTime = System.currentTimeMillis(); if (currentTime - timeOfLastRemoveAction > REMOVE_INTERVAL) {//update every minute removeTimeoutUsers(); // update MostOnline here int currentOnlineUserCount = userMap.size(); fireDataChanged(new OnlineUserEvent(this, currentOnlineUserCount)); } HttpSession session = request.getSession(); String sessionID = session.getId(); OnlineUser user = getOnlineUser(sessionID); if (user == null) { boolean enableLoginInfoInCookie = MVNForumConfig.getEnableLoginInfoInCookie(); boolean enableLoginInfoInSession = MVNForumConfig.getEnableLoginInfoInSession(); boolean enableLoginInfoInRealm = MVNForumConfig.getEnableLoginInfoInRealm(); boolean enableLoginInfoInCustomization = MVNForumConfig.getEnableLoginInfoInCustomization(); if ((user == null) && enableLoginInfoInSession) { String memberName = ParamUtil.getAttribute(session, MVNFORUM_SESSION_USERNAME); String encodedPassword = ParamUtil.getAttribute(session, MVNFORUM_SESSION_PASSWORD); if ( (memberName.length() > 0) && (encodedPassword.length() > 0)) { try { user = login(request, null, memberName, encodedPassword, true); ((OnlineUserImpl) user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_SESSION); } catch (AuthenticationException e) { // do nothing, some time the login info in the session // is not correct, we dont consider this case as error } } } if ((user == null) && enableLoginInfoInCookie) { String memberName = ""; String encodedPassword = ""; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; String cookieName = cookie.getName(); if (cookieName.equals(MVNFORUM_COOKIE_USERNAME)) { memberName = Encoder.decodeURL(cookie.getValue()) ; } else if (cookieName.equals(MVNFORUM_COOKIE_PASSWORD)) { encodedPassword = cookie.getValue(); } } } if ( (memberName.length() > 0) && (encodedPassword.length() > 0) && (encodedPassword.equalsIgnoreCase(PASSWORD_OF_METHOD_REALM) == false) && (encodedPassword.equalsIgnoreCase(PASSWORD_OF_METHOD_CUSTOMIZATION) == false) ) { try { user = login(request, null, memberName, encodedPassword, true); ((OnlineUserImpl)user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_COOKIE); } catch (AuthenticationException e) { // do nothing, some time the login info in the cookie // is not correct, we dont consider this case as error } } } if ((user == null) && enableLoginInfoInRealm && (null != request.getRemoteUser())) { String memberName = StringUtil.getEmptyStringIfNull(request.getRemoteUser()); if ( memberName.length() > 0 ) { try { DAOFactory.getMemberDAO().findByAlternateKey_MemberName(memberName); user = login(request, null, memberName, PASSWORD_OF_METHOD_REALM, true); ((OnlineUserImpl)user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_REALM); } catch (ObjectNotFoundException oe) { // ignore } } } if ((user == null) && enableLoginInfoInCustomization) { if (authenticator == null) { authenticator = ManagerFactory.getAuthenticator(); } if (authenticator != null) { String memberName = StringUtil.getEmptyStringIfNull(authenticator.getRemoteUser(request)); if (memberName.length() > 0) { user = login(request, null, memberName, PASSWORD_OF_METHOD_CUSTOMIZATION, true); ((OnlineUserImpl)user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_CUSTOMIZATION); } } } if (user == null) { user = ManagerFactory.getOnlineUserFactory().getAnonymousUser(request); setOnlineUser(sessionID, user); } } else { //user != null // now we have the user, check if it is a Guest and we can login in REALM boolean enableLoginInfoInRealm = MVNForumConfig.getEnableLoginInfoInRealm(); if (user.isGuest() && enableLoginInfoInRealm && (null != request.getRemoteUser())) { String memberName = StringUtil.getEmptyStringIfNull(request.getRemoteUser()); if ( memberName.length() > 0 ) { try { DAOFactory.getMemberDAO().findByAlternateKey_MemberName(memberName); user = login(request, null, memberName, PASSWORD_OF_METHOD_REALM, true); ((OnlineUserImpl)user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_REALM); } catch (ObjectNotFoundException oe) { // ignore } } } // now we have the user, check if it is a Guest and we can login in CUSTOM boolean enableLoginInfoInCustomization = MVNForumConfig.getEnableLoginInfoInCustomization(); if (authenticator == null) { authenticator = ManagerFactory.getAuthenticator(); } if (authenticator != null) { if (user.isGuest() && enableLoginInfoInCustomization && (null != authenticator.getRemoteUser(request))) { String memberName = StringUtil.getEmptyStringIfNull(authenticator.getRemoteUser(request)); if (memberName.length() > 0) { user = login(request, null, memberName, PASSWORD_OF_METHOD_CUSTOMIZATION, true); ( (OnlineUserImpl) user).setAuthenticationType(OnlineUser.AUTHENTICATION_TYPE_CUSTOMIZATION); } } } } user.getOnlineUserAction().updateLastRequestTime(); return user; } public Collection getOnlineUserActions(int sortOption, boolean duplicateUsers) { Collection collection = userMap.values(); // @todo: find a better sollution, I dont want to copy the Collection // this ArrayList is used to copy the values ArrayList retValue = new ArrayList(collection.size()); // Get members first if (duplicateUsers) { for (Iterator memberIterator = collection.iterator(); memberIterator.hasNext(); ) { OnlineUser onlineUser = (OnlineUser) memberIterator.next(); if (onlineUser.isMember()) { OnlineUserAction onlineUserAction = onlineUser.getOnlineUserAction(); retValue.add(onlineUserAction); } } } else { // now we combine the duplicated users Hashtable distinctUserActions = new Hashtable(); OnlineUserAction lastUserAction = null; for (Iterator memberIterator = collection.iterator(); memberIterator.hasNext(); ) { OnlineUser onlineUser = (OnlineUser) memberIterator.next(); if (onlineUser.isMember()) { OnlineUserAction onlineUserAction = onlineUser.getOnlineUserAction(); String memberName = onlineUserAction.getMemberName(); onlineUserAction.resetSessionCount(); lastUserAction = (OnlineUserAction) distinctUserActions.get(memberName); if (lastUserAction == null) { distinctUserActions.put(memberName, onlineUserAction); } else if (onlineUserAction.getLastRequestTime().after(lastUserAction.getLastRequestTime())) { distinctUserActions.put(memberName, onlineUserAction); onlineUserAction.increaseSessionCount(lastUserAction.getSessionCount()); } else { lastUserAction.increaseSessionCount(1); } } } // now add the distinct member to the returned value Collection distinctCollection = distinctUserActions.values(); for (Iterator iterator = distinctCollection.iterator(); iterator.hasNext(); ) { OnlineUserAction onlineUserAction = (OnlineUserAction)iterator.next(); retValue.add(onlineUserAction); } } // then get guest last for (Iterator guestIterator = collection.iterator(); guestIterator.hasNext(); ) { OnlineUser onlineUser = (OnlineUser)guestIterator.next(); if (onlineUser.isGuest()) { OnlineUserAction onlineUserAction = onlineUser.getOnlineUserAction(); retValue.add(onlineUserAction); } } return retValue; } public void updateOnlineUserAction(HttpServletRequest request, Action action) throws AssertionException, DatabaseException, AuthenticationException { if (action != null) { OnlineUser onlineUser = getOnlineUser(request); OnlineUserAction onlineUserAction = onlineUser.getOnlineUserAction(); // the setAction has package-default access // so this is the only way to set action to a user onlineUserAction.setAction(action); } } public synchronized boolean isUserOnline(String username) { Collection collection = userMap.values(); Iterator iterator = collection.iterator(); while (iterator.hasNext()) { OnlineUser onlineUser = (OnlineUser)iterator.next(); String currentUser = onlineUser.getMemberName(); if (username.equalsIgnoreCase(currentUser)) { return true; } } return false; } /************************************************************************ * private methods ************************************************************************/ private synchronized OnlineUser getOnlineUser(String sessionID) { return (OnlineUser)userMap.get(sessionID); } private synchronized void setOnlineUser(String sessionID, OnlineUser user) { if (null == user) { userMap.remove(sessionID); } else { userMap.put(sessionID, user); } } private synchronized void removeTimeoutUsers() { long currentTimeMillis = System.currentTimeMillis(); // try to resolve problem with synchronization on the class-varible : timeOfLastRemoveAction if (currentTimeMillis - timeOfLastRemoveAction < REMOVE_INTERVAL) { return; } // okie now, go ahead timeOfLastRemoveAction = currentTimeMillis; Timestamp currentTime = DateUtil.getCurrentGMTTimestamp(); Collection collection = userMap.values(); Iterator iterator = collection.iterator(); while (iterator.hasNext()) { OnlineUser onlineUser = (OnlineUser)iterator.next(); OnlineUserAction onlineUserAction = onlineUser.getOnlineUserAction(); long duration = currentTime.getTime() - onlineUserAction.getLastRequestTime().getTime(); if (duration > MVNForumConfig.SESSION_DURATION) { iterator.remove(); } } } /************************************************************************ * Event method ************************************************************************/ public synchronized void removeOnlineUserListener(OnlineUserListener l) { if (onlineUserListeners != null && onlineUserListeners.contains(l)) { Vector v = (Vector) onlineUserListeners.clone(); v.removeElement(l); onlineUserListeners = v; } } public synchronized void addOnlineUserListener(OnlineUserListener l) { Vector v = onlineUserListeners == null ? new Vector(2) : (Vector) onlineUserListeners.clone(); if (!v.contains(l)) { v.addElement(l); onlineUserListeners = v; } } protected void fireDataChanged(OnlineUserEvent e) { if (onlineUserListeners != null) { Vector listeners = onlineUserListeners; int count = listeners.size(); for (int i = 0; i < count; i++) { ((OnlineUserListener) listeners.elementAt(i)).dataChanged(e); } } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.