View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server.session;
20  
21  import java.io.IOException;
22  import java.util.EnumSet;
23  import java.util.EventListener;
24  
25  import javax.servlet.DispatcherType;
26  import javax.servlet.ServletException;
27  import javax.servlet.SessionTrackingMode;
28  import javax.servlet.http.Cookie;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  import javax.servlet.http.HttpSession;
32  
33  import org.eclipse.jetty.http.HttpCookie;
34  import org.eclipse.jetty.server.Request;
35  import org.eclipse.jetty.server.SessionManager;
36  import org.eclipse.jetty.server.handler.ScopedHandler;
37  import org.eclipse.jetty.util.log.Log;
38  import org.eclipse.jetty.util.log.Logger;
39  
40  /* ------------------------------------------------------------ */
41  /**
42   * SessionHandler.
43   */
44  public class SessionHandler extends ScopedHandler
45  {
46      final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
47  
48      public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL);
49  
50  
51      /* -------------------------------------------------------------- */
52      private SessionManager _sessionManager;
53  
54      /* ------------------------------------------------------------ */
55      /**
56       * Constructor. Construct a SessionHandler witha a HashSessionManager with a standard java.util.Random generator is created.
57       */
58      public SessionHandler()
59      {
60          this(new HashSessionManager());
61      }
62  
63      /* ------------------------------------------------------------ */
64      /**
65       * @param manager
66       *            The session manager
67       */
68      public SessionHandler(SessionManager manager)
69      {
70          setSessionManager(manager);
71      }
72  
73      /* ------------------------------------------------------------ */
74      /**
75       * @return Returns the sessionManager.
76       */
77      public SessionManager getSessionManager()
78      {
79          return _sessionManager;
80      }
81  
82      /* ------------------------------------------------------------ */
83      /**
84       * @param sessionManager
85       *            The sessionManager to set.
86       */
87      public void setSessionManager(SessionManager sessionManager)
88      {
89          if (isStarted())
90              throw new IllegalStateException();
91          if (sessionManager != null)
92              sessionManager.setSessionHandler(this);
93          updateBean(_sessionManager,sessionManager);
94          _sessionManager=sessionManager;
95      }
96  
97      /* ------------------------------------------------------------ */
98      /*
99       * @see org.eclipse.thread.AbstractLifeCycle#doStart()
100      */
101     @Override
102     protected void doStart() throws Exception
103     {
104         if (_sessionManager==null)
105             setSessionManager(new HashSessionManager());
106         super.doStart();
107     }
108 
109     /* ------------------------------------------------------------ */
110     /*
111      * @see org.eclipse.thread.AbstractLifeCycle#doStop()
112      */
113     @Override
114     protected void doStop() throws Exception
115     {
116         // Destroy sessions before destroying servlets/filters see JETTY-1266
117         super.doStop();
118     }
119 
120 
121     /* ------------------------------------------------------------ */
122     /*
123      * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
124      */
125     @Override
126     public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
127     {
128         SessionManager old_session_manager = null;
129         HttpSession old_session = null;
130         HttpSession access = null;
131         try
132         {
133             old_session_manager = baseRequest.getSessionManager();
134             old_session = baseRequest.getSession(false);
135 
136             if (old_session_manager != _sessionManager)
137             {
138                 // new session context
139                 baseRequest.setSessionManager(_sessionManager);
140                 baseRequest.setSession(null);
141                 checkRequestedSessionId(baseRequest,request);
142             }
143 
144             // access any existing session
145             HttpSession session = null;
146             if (_sessionManager != null)
147             {
148                 session = baseRequest.getSession(false);
149                 if (session != null)
150                 {
151                     if (session != old_session)
152                     {
153                         access = session;
154                         HttpCookie cookie = _sessionManager.access(session,request.isSecure());
155                         if (cookie != null) // Handle changed ID or max-age refresh
156                             baseRequest.getResponse().addCookie(cookie);
157                     }
158                 }
159                 else
160                 {
161                     session = baseRequest.recoverNewSession(_sessionManager);
162                     if (session != null)
163                         baseRequest.setSession(session);
164                 }
165             }
166 
167             if (LOG.isDebugEnabled())
168             {
169                 LOG.debug("sessionManager=" + _sessionManager);
170                 LOG.debug("session=" + session);
171             }
172 
173             // start manual inline of nextScope(target,baseRequest,request,response);
174             if (_nextScope != null)
175                 _nextScope.doScope(target,baseRequest,request,response);
176             else if (_outerScope != null)
177                 _outerScope.doHandle(target,baseRequest,request,response);
178             else
179                 doHandle(target,baseRequest,request,response);
180             // end manual inline (pathentic attempt to reduce stack depth)
181 
182         }
183         finally
184         {
185             if (access != null)
186                 _sessionManager.complete(access);
187 
188             HttpSession session = baseRequest.getSession(false);
189             if (session != null && old_session == null && session != access)
190                 _sessionManager.complete(session);
191 
192             if (old_session_manager != null && old_session_manager != _sessionManager)
193             {
194                 baseRequest.setSessionManager(old_session_manager);
195                 baseRequest.setSession(old_session);
196             }
197         }
198     }
199 
200     /* ------------------------------------------------------------ */
201     /*
202      * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
203      */
204     @Override
205     public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
206     {
207         // start manual inline of nextHandle(target,baseRequest,request,response);
208         if (never())
209             nextHandle(target,baseRequest,request,response);
210         else if (_nextScope != null && _nextScope == _handler)
211             _nextScope.doHandle(target,baseRequest,request,response);
212         else if (_handler != null)
213             _handler.handle(target,baseRequest,request,response);
214         // end manual inline
215     }
216 
217     /* ------------------------------------------------------------ */
218     /**
219      * Look for a requested session ID in cookies and URI parameters
220      *
221      * @param baseRequest
222      * @param request
223      */
224     protected void checkRequestedSessionId(Request baseRequest, HttpServletRequest request)
225     {
226         String requested_session_id = request.getRequestedSessionId();
227 
228         SessionManager sessionManager = getSessionManager();
229 
230         if (requested_session_id != null && sessionManager != null)
231         {
232             HttpSession session = sessionManager.getHttpSession(requested_session_id);
233             if (session != null && sessionManager.isValid(session))
234                 baseRequest.setSession(session);
235             return;
236         }
237         else if (!DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
238             return;
239 
240         boolean requested_session_id_from_cookie = false;
241         HttpSession session = null;
242 
243         // Look for session id cookie
244         if (_sessionManager.isUsingCookies())
245         {
246             Cookie[] cookies = request.getCookies();
247             if (cookies != null && cookies.length > 0)
248             {
249                 final String sessionCookie=sessionManager.getSessionCookieConfig().getName();
250                 for (int i = 0; i < cookies.length; i++)
251                 {
252                     if (sessionCookie.equalsIgnoreCase(cookies[i].getName()))
253                     {
254                         requested_session_id = cookies[i].getValue();
255                         requested_session_id_from_cookie = true;
256 
257                         LOG.debug("Got Session ID {} from cookie",requested_session_id);
258 
259                         if (requested_session_id != null)
260                         {
261                             session = sessionManager.getHttpSession(requested_session_id);
262 
263                             if (session != null && sessionManager.isValid(session))
264                             {
265                                 break;
266                             }
267                         }
268                         else
269                         {
270                             LOG.warn("null session id from cookie");
271                         }
272                     }
273                 }
274             }
275         }
276 
277         if (requested_session_id == null || session == null)
278         {
279             String uri = request.getRequestURI();
280 
281             String prefix = sessionManager.getSessionIdPathParameterNamePrefix();
282             if (prefix != null)
283             {
284                 int s = uri.indexOf(prefix);
285                 if (s >= 0)
286                 {
287                     s += prefix.length();
288                     int i = s;
289                     while (i < uri.length())
290                     {
291                         char c = uri.charAt(i);
292                         if (c == ';' || c == '#' || c == '?' || c == '/')
293                             break;
294                         i++;
295                     }
296 
297                     requested_session_id = uri.substring(s,i);
298                     requested_session_id_from_cookie = false;
299                     session = sessionManager.getHttpSession(requested_session_id);
300                     if (LOG.isDebugEnabled())
301                         LOG.debug("Got Session ID {} from URL",requested_session_id);
302                 }
303             }
304         }
305 
306         baseRequest.setRequestedSessionId(requested_session_id);
307         baseRequest.setRequestedSessionIdFromCookie(requested_session_id!=null && requested_session_id_from_cookie);
308         if (session != null && sessionManager.isValid(session))
309             baseRequest.setSession(session);
310     }
311 
312     /* ------------------------------------------------------------ */
313     /**
314      * @param listener
315      */
316     public void addEventListener(EventListener listener)
317     {
318         if (_sessionManager != null)
319             _sessionManager.addEventListener(listener);
320     }
321     
322     /* ------------------------------------------------------------ */
323     /**
324      * @param listener
325      */
326     public void removeEventListener(EventListener listener)
327     {
328         if (_sessionManager != null)
329             _sessionManager.removeEventListener(listener);
330     }
331 
332     /* ------------------------------------------------------------ */
333     public void clearEventListeners()
334     {
335         if (_sessionManager != null)
336             _sessionManager.clearEventListeners();
337     }
338 }