1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.shiro.web.session.mgt;
20  
21  import org.apache.shiro.session.ExpiredSessionException;
22  import org.apache.shiro.session.InvalidSessionException;
23  import org.apache.shiro.session.Session;
24  import org.apache.shiro.session.mgt.DefaultSessionManager;
25  import org.apache.shiro.session.mgt.DelegatingSession;
26  import org.apache.shiro.session.mgt.SessionContext;
27  import org.apache.shiro.session.mgt.SessionKey;
28  import org.apache.shiro.web.servlet.Cookie;
29  import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
30  import org.apache.shiro.web.servlet.ShiroHttpSession;
31  import org.apache.shiro.web.servlet.SimpleCookie;
32  import org.apache.shiro.web.util.WebUtils;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import javax.servlet.ServletRequest;
37  import javax.servlet.ServletResponse;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  import java.io.Serializable;
41  
42  
43  
44  
45  
46  
47  
48  public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager {
49  
50      private static final Logger LOGGER = LoggerFactory.getLogger(DefaultWebSessionManager.class);
51  
52      private Cookie sessionIdCookie;
53      private boolean sessionIdCookieEnabled;
54      private boolean sessionIdUrlRewritingEnabled;
55  
56      public DefaultWebSessionManager() {
57          Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
58          
59          cookie.setHttpOnly(true);
60          this.sessionIdCookie = cookie;
61          this.sessionIdCookieEnabled = true;
62          this.sessionIdUrlRewritingEnabled = false;
63      }
64  
65      public Cookie getSessionIdCookie() {
66          return sessionIdCookie;
67      }
68  
69      @SuppressWarnings({"UnusedDeclaration"})
70      public void setSessionIdCookie(Cookie sessionIdCookie) {
71          this.sessionIdCookie = sessionIdCookie;
72      }
73  
74      public boolean isSessionIdCookieEnabled() {
75          return sessionIdCookieEnabled;
76      }
77  
78      @SuppressWarnings({"UnusedDeclaration"})
79      public void setSessionIdCookieEnabled(boolean sessionIdCookieEnabled) {
80          this.sessionIdCookieEnabled = sessionIdCookieEnabled;
81      }
82  
83      public boolean isSessionIdUrlRewritingEnabled() {
84          return sessionIdUrlRewritingEnabled;
85      }
86  
87      @SuppressWarnings({"UnusedDeclaration"})
88      public void setSessionIdUrlRewritingEnabled(boolean sessionIdUrlRewritingEnabled) {
89          this.sessionIdUrlRewritingEnabled = sessionIdUrlRewritingEnabled;
90      }
91  
92      private void storeSessionId(Serializable currentId, HttpServletRequest request, HttpServletResponse response) {
93          if (currentId == null) {
94              String msg = "sessionId cannot be null when persisting for subsequent requests.";
95              throw new IllegalArgumentException(msg);
96          }
97          Cookie template = getSessionIdCookie();
98          Cookie cookie = new SimpleCookie(template);
99          String idString = currentId.toString();
100         cookie.setValue(idString);
101         cookie.saveTo(request, response);
102         LOGGER.trace("Set session ID cookie for session with id {}", idString);
103     }
104 
105     private void removeSessionIdCookie(HttpServletRequest request, HttpServletResponse response) {
106         getSessionIdCookie().removeFrom(request, response);
107     }
108 
109     private String getSessionIdCookieValue(ServletRequest request, ServletResponse response) {
110         if (!isSessionIdCookieEnabled()) {
111             LOGGER.debug("Session ID cookie is disabled - session id will not be acquired from a request cookie.");
112             return null;
113         }
114         if (!(request instanceof HttpServletRequest)) {
115             LOGGER.debug("Current request is not an HttpServletRequest - cannot get session ID cookie.  Returning null.");
116             return null;
117         }
118         HttpServletRequest httpRequest = (HttpServletRequest) request;
119         return getSessionIdCookie().readValue(httpRequest, WebUtils.toHttp(response));
120     }
121 
122     private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
123 
124         String id = getSessionIdCookieValue(request, response);
125         if (id != null) {
126             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
127                     ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
128         } else {
129             
130 
131             
132             id = getUriPathSegmentParamValue(request, ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
133 
134             if (id == null && request instanceof HttpServletRequest) {
135                 
136                 String name = getSessionIdName();
137                 HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
138                 String queryString = httpServletRequest.getQueryString();
139                 if (queryString != null && queryString.contains(name)) {
140                     id = request.getParameter(name);
141                 }
142                 if (id == null && queryString != null && queryString.contains(name.toLowerCase())) {
143                     
144                     id = request.getParameter(name.toLowerCase());
145                 }
146             }
147             if (id != null) {
148                 request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
149                         ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
150             }
151         }
152         if (id != null) {
153             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
154             
155             
156             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
157         }
158 
159         
160         request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, isSessionIdUrlRewritingEnabled());
161 
162         return id;
163     }
164 
165     
166     
167     
168     private String getUriPathSegmentParamValue(ServletRequest servletRequest, String paramName) {
169 
170         if (!(servletRequest instanceof HttpServletRequest)) {
171             return null;
172         }
173         HttpServletRequest request = (HttpServletRequest) servletRequest;
174         String uri = request.getRequestURI();
175         if (uri == null) {
176             return null;
177         }
178 
179         int queryStartIndex = uri.indexOf('?');
180         
181         if (queryStartIndex >= 0) {
182             uri = uri.substring(0, queryStartIndex);
183         }
184 
185         
186         int index = uri.indexOf(';');
187         if (index < 0) {
188             
189             return null;
190         }
191 
192         
193         final String token = paramName + "=";
194 
195         
196         uri = uri.substring(index + 1);
197 
198         
199         index = uri.lastIndexOf(token);
200         if (index < 0) {
201             
202             return null;
203         }
204 
205         uri = uri.substring(index + token.length());
206 
207         
208         index = uri.indexOf(';');
209         if (index >= 0) {
210             uri = uri.substring(0, index);
211         }
212 
213         
214         return uri;
215     }
216 
217     
218     private String getSessionIdName() {
219         String name = this.sessionIdCookie != null ? this.sessionIdCookie.getName() : null;
220         if (name == null) {
221             name = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
222         }
223         return name;
224     }
225 
226     protected Session createExposedSession(Session session, SessionContext context) {
227         if (!WebUtils.isWeb(context)) {
228             return super.createExposedSession(session, context);
229         }
230         ServletRequest request = WebUtils.getRequest(context);
231         ServletResponse response = WebUtils.getResponse(context);
232         SessionKey key = new WebSessionKey(session.getId(), request, response);
233         return new DelegatingSession(this, key);
234     }
235 
236     protected Session createExposedSession(Session session, SessionKey key) {
237         if (!WebUtils.isWeb(key)) {
238             return super.createExposedSession(session, key);
239         }
240 
241         ServletRequest request = WebUtils.getRequest(key);
242         ServletResponse response = WebUtils.getResponse(key);
243         SessionKey sessionKey = new WebSessionKey(session.getId(), request, response);
244         return new DelegatingSession(this, sessionKey);
245     }
246 
247     
248 
249 
250 
251 
252     @Override
253     protected void onStart(Session session, SessionContext context) {
254         super.onStart(session, context);
255 
256         if (!WebUtils.isHttp(context)) {
257             LOGGER.debug("SessionContext argument is not HTTP compatible or does not have an HTTP request/response "
258                     + "pair. No session ID cookie will be set.");
259             return;
260 
261         }
262         HttpServletRequest request = WebUtils.getHttpRequest(context);
263         HttpServletResponse response = WebUtils.getHttpResponse(context);
264 
265         if (isSessionIdCookieEnabled()) {
266             Serializable sessionId = session.getId();
267             storeSessionId(sessionId, request, response);
268         } else {
269             LOGGER.debug("Session ID cookie is disabled.  No cookie has been set for new session with id {}", session.getId());
270         }
271 
272         request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
273         request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
274     }
275 
276     @Override
277     public Serializable getSessionId(SessionKey key) {
278         Serializable id = super.getSessionId(key);
279         if (id == null && WebUtils.isWeb(key)) {
280             ServletRequest request = WebUtils.getRequest(key);
281             ServletResponse response = WebUtils.getResponse(key);
282             id = getSessionId(request, response);
283         }
284         return id;
285     }
286 
287     protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
288         return getReferencedSessionId(request, response);
289     }
290 
291     @Override
292     protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
293         super.onExpiration(s, ese, key);
294         onInvalidation(key);
295     }
296 
297     @Override
298     protected void onInvalidation(Session session, InvalidSessionException ise, SessionKey key) {
299         super.onInvalidation(session, ise, key);
300         onInvalidation(key);
301     }
302 
303     private void onInvalidation(SessionKey key) {
304         ServletRequest request = WebUtils.getRequest(key);
305         if (request != null) {
306             request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID);
307         }
308         if (WebUtils.isHttp(key)) {
309             LOGGER.debug("Referenced session was invalid.  Removing session ID cookie.");
310             removeSessionIdCookie(WebUtils.getHttpRequest(key), WebUtils.getHttpResponse(key));
311         } else {
312             LOGGER.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response "
313                     + "pair. Session ID cookie will not be removed due to invalidated session.");
314         }
315     }
316 
317     @Override
318     protected void onStop(Session session, SessionKey key) {
319         super.onStop(session, key);
320         if (WebUtils.isHttp(key)) {
321             HttpServletRequest request = WebUtils.getHttpRequest(key);
322             HttpServletResponse response = WebUtils.getHttpResponse(key);
323             LOGGER.debug("Session has been stopped (subject logout or explicit stop).  Removing session ID cookie.");
324             removeSessionIdCookie(request, response);
325         } else {
326             LOGGER.debug("SessionKey argument is not HTTP compatible or does not have an HTTP request/response "
327                     + "pair. Session ID cookie will not be removed due to stopped session.");
328         }
329     }
330 
331     
332 
333 
334 
335 
336 
337     public boolean isServletContainerSessions() {
338         return false;
339     }
340 }