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