/*
* $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Portal/Sources/es/udc/mypersonalizer/portal/controller/filters/SessionPreProcessingFilter.java,v 1.1.1.1 2004/03/25 12:08:40 fbellas Exp $
* $Revision: 1.1.1.1 $
* $Date: 2004/03/25 12:08:40 $
*
* =============================================================================
*
* Copyright (c) 2003, The MyPersonalizer Development Group
* (http://www.tic.udc.es/~fbellas/mypersonalizer/index.html) at
* University Of A Coruna
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - 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.
*
* - Neither the name of the University Of A Coruna nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 es.udc.mypersonalizer.portal.controller.filters;
import es.udc.mypersonalizer.kernel.conventions.
UserAndGroupConventions;
import es.udc.mypersonalizer.kernel.model.actions.
ActionProcessorSingleton;
import es.udc.mypersonalizer.kernel.util.exceptions.
IncorrectPasswordException;
import es.udc.mypersonalizer.kernel.util.exceptions.
InstanceNotFoundException;
import es.udc.mypersonalizer.kernel.util.exceptions.
InternalErrorException;
import es.udc.mypersonalizer.kernel.util.exceptions.
ModelException;
import es.udc.mypersonalizer.kernel.controller.requestprocessor.
AbstractPreProcessingFilter;
import es.udc.mypersonalizer.kernel.controller.requestprocessor.
PreProcessingFilter;
import es.udc.mypersonalizer.portal.controller.session.
SessionIdentifierCookieManagerSingleton;
import es.udc.mypersonalizer.portal.controller.session.
SessionManager;
import es.udc.mypersonalizer.portal.model.types.user.
SignInEvent;
import es.udc.mypersonalizer.portal.model.types.user.
SignInResult;
import es.udc.mypersonalizer.portal.model.permissions.
UserCredentials;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
/**
* This filter processes users' requests and takes into account all session
* stuff.<p>
*
* It must assure that session is initialized and that all the necessary
* session information is correctly stored session-wide.<p>
*
* It works the following way:
* <ul>
* <li>Calls <tt>isSessionInitializedForAuthenticatedUser</tt>, which
* checks if all the needed information is in the request. The method
* in this class only performs a call to
* {@link SessionManager}.isUserAuthenticated, but it can be extended
* in a subclass to perform further checking.<br>
* If the session is not completely initialized, there are two
* possibilities:
* <ol>
* <li>The user may be authenticated, which may mean he or she has
* authenticated but still not all the needed data has been put into
* the session. So, <tt>intializeSessionForAuthenticatedUser</tt>
* is called.</li>
* <li>The user may not be authenticated. Then,
* {@link SessionManager}.isSessionInitialized is called and again,
* we have two possibilities:
* <ol>
* <li>The session is initialized, according to
* <tt>SessionManager</tt>, which means the session
* already has the data for the <tt>anonymous</tt> user.</li>
* <li>The session is not initialized, according to
* <tt>SessionManager</tt>, it means that the user has just
* arrived at the portal and thus he or she may be provinding
* the system with a cookie which can be used to log him or
* her in.
* {@link SessionIdentifierCookieManagerSingleton}.validateAndLogin
* is called for this purpose, and:
* <ul>
* <li>If the login operation succeeds,
* <tt>SessionManager.initializeSession</tt> and
* <tt>initializeSessionForAuthenticatedUser</tt> are
* called to initialize the session.</li>
* <li>If the login operation does not succeed, then a
* login operation is made for the <tt>anonymous</tt>
* user and <tt>SessionManager.initializeSession</tt>
* is called, with the <tt>userAuthenticated</tt>
* parameter set to true, because the <tt>anonymous</tt>
* has not logged in through the log in form.</li>
* </ul>
* </li>
* </ol>
* </li>
* </ol>
* </li>
* </ul>
*
* This filter can be extended by creating a subclass of it and redefining
* isSessionInitializedForAuthenticatedUser and
* initializeSessionForAuthenticatedUser, so as to modify the system behaviour
* to store as much information in session as the developer may want.
*
* @author Daniel Fernandez
* @author Fernando Bellas
* @since 1.0
*/
public class SessionPreProcessingFilter extends AbstractPreProcessingFilter {
/**
* Name of the model action for signing in.
* This is "SignInAction".
*/
private static final String SIGN_IN_ACTION = "SignInAction";
/**
* Creates an instance of this filter and links the next filter in the
* chain
*
* @param next the next PreProcessingFilter in the chain
*/
public SessionPreProcessingFilter(PreProcessingFilter next) {
setNextFilter(next);
}
/**
* Creates an instance of this filter without linking the next filter in the
* chain
*
*/
public SessionPreProcessingFilter() {
setNextFilter(null);
}
/**
* Checks whether all the required information resides in the session.
*
* @return a boolean with TRUE if session is ok, FALSE if not
* @param request the request for which check its session
*/
protected boolean isSessionInitializedForAuthenticatedUser(
HttpServletRequest request) {
/*
* Nothing else to do in this version of SessionPreProcessingFilter
*/
return (SessionManager.isUserAuthenticated(request));
}
/**
* Loads the session with all the information that is required to live
* there and that is not pushed into the session by
* SessionManager.initializeSession. <p>
*
* This version of SessionPreProcessingFilter does nothing for this method.
*
* @param request the request that session the filter has to load
*/
protected void initializeSessionForAuthenticatedUser(
HttpServletRequest request) {
/*
* Nothing to do in this version of SessionPreProcessingFilter
*/
}
protected ActionForward doProcess(HttpServletRequest request,
HttpServletResponse response, Action action, ActionForm form,
ActionMapping mapping)
throws InternalErrorException {
/* We MUST have a session */
HttpSession session = request.getSession(true);
if (!isSessionInitializedForAuthenticatedUser(request)) {
/*
* So, not all of the needed information (maybe none) resides
* in the session
*/
if (SessionManager.isUserAuthenticated(request)) {
/*
* As we know the session is not correctly initialized but the
* user credentials already reside in the sesion, this can only
* mean that the user has just signed in and thus only the
* mandatory info (the data managed by the SessionManager) has
* been pushed into the session.
*/
initializeSessionForAuthenticatedUser(request);
} else {
if (SessionManager.isSessionInitialized(request)) {
/*
* This means we already have anonymous at the session
*/
return null;
} else {
SessionIdentifierCookieManagerSingleton
sessionIdentifierCookieManagerSingleton =
SessionIdentifierCookieManagerSingleton.
getInstance();
/*
* Checks whether the user's browser already has the session
* cookie and, if it has it, tries to validate its info,
* log the user and return a SignInResult
*/
SignInResult signInResult =
sessionIdentifierCookieManagerSingleton.
validateAndLogin(request);
if (signInResult != null) {
SessionManager.
initializeSession(request,signInResult,true);
/*
* As we have got the user's login name from the session
* cookie, this means that the session had simply
* expired, and thus we can safely reconstruct the
* session for the
* user transparently
*/
initializeSessionForAuthenticatedUser(request);
} else {
/*
* We could not authenticate the user, so we'll
* sign the anonymous user in.
*/
signInResult = performAnonymousSignIn();
SessionManager.
initializeSession(request,signInResult,false);
}
}
}
}
return null;
}
private SignInResult performAnonymousSignIn()
throws InternalErrorException {
SignInEvent signInEvent = new SignInEvent(new UserCredentials(
UserAndGroupConventions.ANONYMOUS_LOGIN_NAME, null),
null, false);
try {
ActionProcessorSingleton actionProcessorSingleton =
ActionProcessorSingleton.getInstance();
SignInResult signInResult = (SignInResult)
actionProcessorSingleton.execute(SIGN_IN_ACTION, signInEvent);
return signInResult;
} catch (InstanceNotFoundException e) {
// This should NEVER happen, anonymous must exist
throw new InternalErrorException(e);
} catch (IncorrectPasswordException e) {
// This should NEVER happen, we don't need password here
throw new InternalErrorException(e);
} catch (ModelException e) {
/* This should never happen. */
throw new InternalErrorException(e);
}
}
}
|