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 }