| // |
| // ======================================================================== |
| // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.server.session; |
| |
| import java.io.IOException; |
| import java.util.EnumSet; |
| import java.util.EventListener; |
| |
| import javax.servlet.DispatcherType; |
| import javax.servlet.ServletException; |
| import javax.servlet.SessionTrackingMode; |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| import javax.servlet.http.HttpSessionAttributeListener; |
| import javax.servlet.http.HttpSessionIdListener; |
| import javax.servlet.http.HttpSessionListener; |
| |
| import org.eclipse.jetty.http.HttpCookie; |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.SessionManager; |
| import org.eclipse.jetty.server.handler.ScopedHandler; |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * SessionHandler. |
| */ |
| public class SessionHandler extends ScopedHandler |
| { |
| final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session"); |
| |
| public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL); |
| |
| @SuppressWarnings("unchecked") |
| public static final Class<? extends EventListener>[] SESSION_LISTENER_TYPES = |
| new Class[] {HttpSessionAttributeListener.class, |
| HttpSessionIdListener.class, |
| HttpSessionListener.class}; |
| |
| |
| |
| /* -------------------------------------------------------------- */ |
| private SessionManager _sessionManager; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Constructor. Construct a SessionHandler witha a HashSessionManager with a standard java.util.Random generator is created. |
| */ |
| public SessionHandler() |
| { |
| this(new HashSessionManager()); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param manager |
| * The session manager |
| */ |
| public SessionHandler(SessionManager manager) |
| { |
| setSessionManager(manager); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return Returns the sessionManager. |
| */ |
| public SessionManager getSessionManager() |
| { |
| return _sessionManager; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param sessionManager |
| * The sessionManager to set. |
| */ |
| public void setSessionManager(SessionManager sessionManager) |
| { |
| if (isStarted()) |
| throw new IllegalStateException(); |
| if (sessionManager != null) |
| sessionManager.setSessionHandler(this); |
| updateBean(_sessionManager,sessionManager); |
| _sessionManager=sessionManager; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* |
| * @see org.eclipse.thread.AbstractLifeCycle#doStart() |
| */ |
| @Override |
| protected void doStart() throws Exception |
| { |
| if (_sessionManager==null) |
| setSessionManager(new HashSessionManager()); |
| super.doStart(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* |
| * @see org.eclipse.thread.AbstractLifeCycle#doStop() |
| */ |
| @Override |
| protected void doStop() throws Exception |
| { |
| // Destroy sessions before destroying servlets/filters see JETTY-1266 |
| super.doStop(); |
| } |
| |
| |
| /* ------------------------------------------------------------ */ |
| /* |
| * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) |
| */ |
| @Override |
| public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException |
| { |
| SessionManager old_session_manager = null; |
| HttpSession old_session = null; |
| HttpSession access = null; |
| try |
| { |
| old_session_manager = baseRequest.getSessionManager(); |
| old_session = baseRequest.getSession(false); |
| |
| if (old_session_manager != _sessionManager) |
| { |
| // new session context |
| baseRequest.setSessionManager(_sessionManager); |
| baseRequest.setSession(null); |
| checkRequestedSessionId(baseRequest,request); |
| } |
| |
| // access any existing session |
| HttpSession session = null; |
| if (_sessionManager != null) |
| { |
| session = baseRequest.getSession(false); |
| if (session != null) |
| { |
| if ((session != old_session) && (request.getDispatcherType() == DispatcherType.ASYNC || request.getDispatcherType() == DispatcherType.REQUEST)) |
| { |
| access = session; |
| HttpCookie cookie = _sessionManager.access(session,request.isSecure()); |
| if (cookie != null) // Handle changed ID or max-age refresh |
| baseRequest.getResponse().addCookie(cookie); |
| } |
| } |
| else |
| { |
| session = baseRequest.recoverNewSession(_sessionManager); |
| if (session != null) |
| baseRequest.setSession(session); |
| } |
| } |
| |
| if (LOG.isDebugEnabled()) |
| { |
| LOG.debug("sessionManager=" + _sessionManager); |
| LOG.debug("session=" + session); |
| } |
| |
| // start manual inline of nextScope(target,baseRequest,request,response); |
| if (_nextScope != null) |
| _nextScope.doScope(target,baseRequest,request,response); |
| else if (_outerScope != null) |
| _outerScope.doHandle(target,baseRequest,request,response); |
| else |
| doHandle(target,baseRequest,request,response); |
| // end manual inline (pathentic attempt to reduce stack depth) |
| |
| } |
| finally |
| { |
| //if we accessed an existing session entering this context, then complete it |
| if (access != null) |
| _sessionManager.complete(access); |
| |
| |
| //if there is a session that was created during handling this context, then complete it |
| HttpSession session = baseRequest.getSession(false); |
| if ((session != null && old_session == null && session != access) && (request.getDispatcherType() == DispatcherType.ASYNC || request.getDispatcherType() == DispatcherType.REQUEST)) |
| _sessionManager.complete(session); |
| |
| if (old_session_manager != null && old_session_manager != _sessionManager) |
| { |
| baseRequest.setSessionManager(old_session_manager); |
| baseRequest.setSession(old_session); |
| } |
| } |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* |
| * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) |
| */ |
| @Override |
| public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException |
| { |
| // start manual inline of nextHandle(target,baseRequest,request,response); |
| if (never()) |
| nextHandle(target,baseRequest,request,response); |
| else if (_nextScope != null && _nextScope == _handler) |
| _nextScope.doHandle(target,baseRequest,request,response); |
| else if (_handler != null) |
| _handler.handle(target,baseRequest,request,response); |
| // end manual inline |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Look for a requested session ID in cookies and URI parameters |
| * |
| * @param baseRequest the request to check |
| * @param request the request to check |
| */ |
| protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request) |
| { |
| String requested_session_id = request.getRequestedSessionId(); |
| |
| SessionManager sessionManager = getSessionManager(); |
| |
| if (requested_session_id != null && sessionManager != null) |
| { |
| HttpSession session = sessionManager.getHttpSession(requested_session_id); |
| |
| if (session != null && sessionManager.isValid(session)) |
| baseRequest.setSession(session); |
| return; |
| } |
| else if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) |
| return; |
| |
| boolean requested_session_id_from_cookie = false; |
| HttpSession session = null; |
| |
| // Look for session id cookie |
| if (_sessionManager.isUsingCookies()) |
| { |
| Cookie[] cookies = request.getCookies(); |
| if (cookies != null && cookies.length > 0) |
| { |
| final String sessionCookie=sessionManager.getSessionCookieConfig().getName(); |
| for (int i = 0; i < cookies.length; i++) |
| { |
| if (sessionCookie.equalsIgnoreCase(cookies[i].getName())) |
| { |
| requested_session_id = cookies[i].getValue(); |
| requested_session_id_from_cookie = true; |
| |
| if (LOG.isDebugEnabled()) |
| LOG.debug("Got Session ID {} from cookie",requested_session_id); |
| |
| if (requested_session_id != null) |
| { |
| session = sessionManager.getHttpSession(requested_session_id); |
| if (session != null && sessionManager.isValid(session)) |
| { |
| break; |
| } |
| } |
| else |
| { |
| LOG.warn("null session id from cookie"); |
| } |
| } |
| } |
| } |
| } |
| |
| if (requested_session_id == null || session == null) |
| { |
| String uri = request.getRequestURI(); |
| |
| String prefix = sessionManager.getSessionIdPathParameterNamePrefix(); |
| if (prefix != null) |
| { |
| int s = uri.indexOf(prefix); |
| if (s >= 0) |
| { |
| s += prefix.length(); |
| int i = s; |
| while (i < uri.length()) |
| { |
| char c = uri.charAt(i); |
| if (c == ';' || c == '#' || c == '?' || c == '/') |
| break; |
| i++; |
| } |
| |
| requested_session_id = uri.substring(s,i); |
| requested_session_id_from_cookie = false; |
| session = sessionManager.getHttpSession(requested_session_id); |
| if (LOG.isDebugEnabled()) |
| LOG.debug("Got Session ID {} from URL",requested_session_id); |
| } |
| } |
| } |
| |
| baseRequest.setRequestedSessionId(requested_session_id); |
| baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie); |
| if (session != null && sessionManager.isValid(session)) |
| baseRequest.setSession(session); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void addEventListener(EventListener listener) |
| { |
| if (_sessionManager != null) |
| _sessionManager.addEventListener(listener); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void removeEventListener(EventListener listener) |
| { |
| if (_sessionManager != null) |
| _sessionManager.removeEventListener(listener); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void clearEventListeners() |
| { |
| if (_sessionManager != null) |
| _sessionManager.clearEventListeners(); |
| } |
| } |