Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.jsecurity.web.session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jsecurity.authz.AuthorizationException; import org.jsecurity.authz.HostUnauthorizedException; import org.jsecurity.session.InvalidSessionException; import org.jsecurity.session.Session; import org.jsecurity.session.mgt.DefaultSessionManager; import org.jsecurity.web.WebUtils; import org.jsecurity.web.attr.CookieAttribute; import org.jsecurity.web.attr.RequestParamAttribute; import org.jsecurity.web.attr.WebAttribute; import org.jsecurity.web.servlet.JSecurityHttpServletRequest; import org.jsecurity.web.servlet.JSecurityHttpSession; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.Serializable; import java.net.InetAddress; /** * Web-application capable <tt>SessionManager</tt> implementation. * * @author Les Hazlewood * @since 0.9 */ public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager { //TODO - complete JavaDoc private static final Log log = LogFactory.getLog(DefaultWebSessionManager.class); /** * Property specifying if, after a session object is acquired from the request, if that session should be * validated to ensure the starting origin of the session is the same as the incoming request. */ private boolean validateRequestOrigin = false; //default protected CookieAttribute<Serializable> sessionIdCookieAttribute = null; protected RequestParamAttribute<Serializable> sessionIdRequestParamAttribute = null; public DefaultWebSessionManager() { ensureCookieSessionIdStore(); ensureRequestParamSessionIdStore(); } public CookieAttribute<Serializable> getSessionIdCookieAttribute() { return sessionIdCookieAttribute; } public void setSessionIdCookieAttribute(CookieAttribute<Serializable> sessionIdCookieAttribute) { this.sessionIdCookieAttribute = sessionIdCookieAttribute; } public RequestParamAttribute<Serializable> getSessionIdRequestParamAttribute() { return sessionIdRequestParamAttribute; } public void setSessionIdRequestParamAttribute( RequestParamAttribute<Serializable> sessionIdRequestParamAttribute) { this.sessionIdRequestParamAttribute = sessionIdRequestParamAttribute; } /** * If set to <tt>true</tt>, this implementation will ensure that any * <tt>HttpRequest</tt> attempting * to join a session (i.e. via {@link #getSession getSession} must have the same * IP Address of the <tt>HttpRequest</tt> that started the session. * * <p> If set to <tt>false</tt>, any <tt>HttpRequest</tt> with a reference to a valid * session id may acquire that <tt>Session</tt>. * * <p>Although convenient, this should only be enabled in environments where the * system can <em>guarantee</em> that each IP address represents one and only one * machine accessing the system. * * <p>Public websites are not good candidates for enabling this * feature since many browser clients often sit behind NAT routers (in * which case many machines are viewed to come from the same IP, thereby making this * validation check useless). Also, some internet service providers (e.g. AOL) may change a * client's IP in mid-session, making subsequent requests appear to come from a different * location. Again, this feature should only be enabled where IP Addresses can be guaranteed a * 1-to-1 relationship with a user's session. * * <p>For the reasons specified above, this property is <tt>false</tt> by default. * * @return true if this factory will verify each HttpRequest joining a session */ public boolean isValidateRequestOrigin() { return validateRequestOrigin; } /** * Sets whether or not a request's origin will be validated when accessing a session. See * the {@link #isValidateRequestOrigin} JavaDoc for an in-depth explanation of this property. * * @param validateRequestOrigin whether or not to validate the request's origin when accessing * a session. * @see #isValidateRequestOrigin */ public void setValidateRequestOrigin(boolean validateRequestOrigin) { this.validateRequestOrigin = validateRequestOrigin; } public void setSessionIdCookieName(String name) { getSessionIdCookieAttribute().setName(name); } public void setSessionIdCookiePath(String path) { getSessionIdCookieAttribute().setPath(path); } public void setSessionIdCookieMaxAge(int maxAge) { getSessionIdCookieAttribute().setMaxAge(maxAge); } public void setSessionIdCookieSecure(boolean secure) { getSessionIdCookieAttribute().setSecure(secure); } protected void ensureCookieSessionIdStore() { CookieAttribute<Serializable> cookieStore = getSessionIdCookieAttribute(); if (cookieStore == null) { cookieStore = new CookieAttribute<Serializable>(JSecurityHttpSession.DEFAULT_SESSION_ID_NAME); cookieStore.setCheckRequestParams(false); setSessionIdCookieAttribute(cookieStore); } } protected void ensureRequestParamSessionIdStore() { RequestParamAttribute<Serializable> reqParamStore = getSessionIdRequestParamAttribute(); if (reqParamStore == null) { reqParamStore = new RequestParamAttribute<Serializable>(JSecurityHttpSession.DEFAULT_SESSION_ID_NAME); setSessionIdRequestParamAttribute(reqParamStore); } } protected void validateSessionOrigin(ServletRequest request, Session session) throws HostUnauthorizedException { InetAddress requestIp = WebUtils.getInetAddress(request); InetAddress originIp = session.getHostAddress(); Serializable sessionId = session.getId(); if (originIp == null) { if (requestIp != null) { String msg = "No IP Address was specified when creating session with id [" + sessionId + "]. Attempting to access session from " + "IP [" + requestIp + "]. Origin IP and request IP must match."; throw new HostUnauthorizedException(msg); } } else { if (requestIp != null) { if (!requestIp.equals(originIp)) { String msg = "Session with id [" + sessionId + "] originated from [" + originIp + "], but the current HttpServletRequest originated " + "from [" + requestIp + "]. Disallowing session access: " + "session origin and request origin must match to allow access."; throw new HostUnauthorizedException(msg); } } else { String msg = "No IP Address associated with the current HttpServletRequest. " + "Session with id [" + sessionId + "] originated from " + "[" + originIp + "]. Request IP must match the session's origin " + "IP in order to gain access to that session."; throw new HostUnauthorizedException(msg); } } } protected void storeSessionId(Serializable currentId, ServletRequest request, ServletResponse response) { if (currentId == null) { String msg = "sessionId cannot be null when persisting for subsequent requests."; throw new IllegalArgumentException(msg); } //ensure that the id has been set in the idStore, or if it already has, that it is not different than the //'real' session value: Serializable existingId = retrieveSessionId(request, response); if (existingId == null || !currentId.equals(existingId)) { getSessionIdCookieAttribute().storeValue(currentId, request, response); } } protected Serializable retrieveSessionId(ServletRequest request, ServletResponse response) { WebAttribute<Serializable> cookieSessionIdAttribute = getSessionIdCookieAttribute(); Serializable id = cookieSessionIdAttribute.retrieveValue(request, response); if (id != null) { request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, JSecurityHttpServletRequest.COOKIE_SESSION_ID_SOURCE); } else { id = getSessionIdRequestParamAttribute().retrieveValue(request, response); if (id != null) { request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, JSecurityHttpServletRequest.URL_SESSION_ID_SOURCE); } } return id; } public Serializable start(InetAddress hostAddress) throws HostUnauthorizedException, IllegalArgumentException { ServletRequest request = WebUtils.getRequiredServletRequest(); ServletResponse response = WebUtils.getRequiredServletResponse(); return start(request, response, hostAddress); } protected Serializable start(ServletRequest request, ServletResponse response, InetAddress inetAddress) { Serializable sessionId = super.start(inetAddress); storeSessionId(sessionId, request, response); request.removeAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE); request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE); return sessionId; } public Session retrieveSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException { if (sessionId != null) { return super.retrieveSession(sessionId); } else { ServletRequest request = WebUtils.getRequiredServletRequest(); ServletResponse response = WebUtils.getRequiredServletResponse(); return getSession(request, response); } } /** * Returns the Session associated with the specified request if it is valid or <tt>null</tt> if a Session doesn't * exist or it was invalid. * * @param request incoming servlet request * @param response outgoing servlet response * @return the Session associated with the incoming request or <tt>null</tt> if one does not exist. * @throws org.jsecurity.session.InvalidSessionException * if the associated Session has expired prior to invoking this method. * @throws org.jsecurity.authz.AuthorizationException * if the caller is not authorized to access the session associated with the request. */ public final Session getSession(ServletRequest request, ServletResponse response) throws InvalidSessionException, AuthorizationException { Session session; try { session = doGetSession(request, response); } catch (InvalidSessionException ise) { if (log.isTraceEnabled()) { log.trace("Request Session is invalid, message: [" + ise.getMessage() + "]. Removing any " + "associated session cookie..."); } getSessionIdCookieAttribute().removeValue(request, response); //give subclass a chance to do something additional if necessary. Otherwise returning null is just fine: session = handleInvalidSession(request, response, ise); } return session; } protected Session doGetSession(ServletRequest request, ServletResponse response) { Session session = null; Serializable sessionId = retrieveSessionId(request, response); if (sessionId != null) { request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID, sessionId); session = super.retrieveSession(sessionId); if (isValidateRequestOrigin()) { if (log.isDebugEnabled()) { log.debug("Validating request origin against session origin"); } validateSessionOrigin(request, session); } if (session != null) { request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); } } else { if (log.isTraceEnabled()) { log.trace("No JSecurity session id associated with the given " + "HttpServletRequest. A Session will not be returned."); } } return session; } protected Session handleInvalidSession(ServletRequest request, ServletResponse response, InvalidSessionException ise) { if (log.isTraceEnabled()) { log.trace("Sesssion associated with the current request is nonexistent or invalid. Returning null."); } return null; } protected void onStop(Session session) { super.onStop(session); ServletRequest request = WebUtils.getRequiredServletRequest(); ServletResponse response = WebUtils.getRequiredServletResponse(); getSessionIdCookieAttribute().removeValue(request, response); } }