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