View Javadoc

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