View Javadoc

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