1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server.session;
20
21 import static java.lang.Math.round;
22
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.CopyOnWriteArrayList;
30
31 import javax.servlet.ServletRequest;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpSession;
34 import javax.servlet.http.HttpSessionAttributeListener;
35 import javax.servlet.http.HttpSessionBindingEvent;
36 import javax.servlet.http.HttpSessionContext;
37 import javax.servlet.http.HttpSessionEvent;
38 import javax.servlet.http.HttpSessionListener;
39
40 import org.eclipse.jetty.http.HttpCookie;
41 import org.eclipse.jetty.server.AbstractConnector;
42 import org.eclipse.jetty.server.Request;
43 import org.eclipse.jetty.server.Server;
44 import org.eclipse.jetty.server.SessionIdManager;
45 import org.eclipse.jetty.server.SessionManager;
46 import org.eclipse.jetty.server.handler.ContextHandler;
47 import org.eclipse.jetty.util.component.AbstractLifeCycle;
48 import org.eclipse.jetty.util.log.Logger;
49 import org.eclipse.jetty.util.statistic.CounterStatistic;
50 import org.eclipse.jetty.util.statistic.SampleStatistic;
51
52
53
54
55
56
57
58
59
60
61
62 @SuppressWarnings("deprecation")
63 public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
64 {
65 final static Logger __log = SessionHandler.LOG;
66 public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated";
67
68
69 public final static int __distantFuture=60*60*24*7*52*20;
70
71 static final HttpSessionContext __nullSessionContext=new HttpSessionContext()
72 {
73 public HttpSession getSession(String sessionId)
74 {
75 return null;
76 }
77
78 @SuppressWarnings({ "rawtypes", "unchecked" })
79 public Enumeration getIds()
80 {
81 return Collections.enumeration(Collections.EMPTY_LIST);
82 }
83 };
84
85 private boolean _usingCookies=true;
86
87
88
89
90 protected int _dftMaxIdleSecs=-1;
91 protected SessionHandler _sessionHandler;
92 protected boolean _httpOnly=false;
93 protected SessionIdManager _sessionIdManager;
94 protected boolean _secureCookies=false;
95 protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
96 protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
97
98 protected ClassLoader _loader;
99 protected ContextHandler.Context _context;
100 protected String _sessionCookie=__DefaultSessionCookie;
101 protected String _sessionIdPathParameterName = __DefaultSessionIdPathParameterName;
102 protected String _sessionIdPathParameterNamePrefix =";"+ _sessionIdPathParameterName +"=";
103 protected String _sessionDomain;
104 protected String _sessionPath;
105 protected int _maxCookieAge=-1;
106 protected int _refreshCookieAge;
107 protected boolean _nodeIdInSessionId;
108 protected boolean _checkingRemoteSessionIdEncoding;
109
110 protected final CounterStatistic _sessionsStats = new CounterStatistic();
111 protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
112
113
114
115 public static HttpSession renewSession (HttpServletRequest request, HttpSession httpSession, boolean authenticated)
116 {
117 Map<String,Object> attributes = new HashMap<String, Object>();
118
119 for (Enumeration<String> e=httpSession.getAttributeNames();e.hasMoreElements();)
120 {
121 String name=e.nextElement();
122 attributes.put(name,httpSession.getAttribute(name));
123 httpSession.removeAttribute(name);
124 }
125
126 httpSession.invalidate();
127 httpSession = request.getSession(true);
128 if (authenticated)
129 httpSession.setAttribute(SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE);
130 for (Map.Entry<String, Object> entry: attributes.entrySet())
131 httpSession.setAttribute(entry.getKey(),entry.getValue());
132 return httpSession;
133 }
134
135
136 public AbstractSessionManager()
137 {
138 }
139
140
141 public ContextHandler.Context getContext()
142 {
143 return _context;
144 }
145
146
147 public ContextHandler getContextHandler()
148 {
149 return _context.getContextHandler();
150 }
151
152
153 public HttpCookie access(HttpSession session,boolean secure)
154 {
155 long now=System.currentTimeMillis();
156
157 AbstractSession s = ((SessionIf)session).getSession();
158
159 if (s.access(now))
160 {
161
162 if (isUsingCookies() &&
163 (s.isIdChanged() ||
164 (getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
165 )
166 )
167 {
168 HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
169 s.cookieSet();
170 s.setIdChanged(false);
171 return cookie;
172 }
173 }
174 return null;
175 }
176
177
178 public void addEventListener(EventListener listener)
179 {
180 if (listener instanceof HttpSessionAttributeListener)
181 _sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
182 if (listener instanceof HttpSessionListener)
183 _sessionListeners.add((HttpSessionListener)listener);
184 }
185
186
187 public void clearEventListeners()
188 {
189 _sessionAttributeListeners.clear();
190 _sessionListeners.clear();
191 }
192
193
194 public void complete(HttpSession session)
195 {
196 AbstractSession s = ((SessionIf)session).getSession();
197 s.complete();
198 }
199
200
201 @Override
202 public void doStart() throws Exception
203 {
204 _context=ContextHandler.getCurrentContext();
205 _loader=Thread.currentThread().getContextClassLoader();
206
207 if (_sessionIdManager==null)
208 {
209 final Server server=getSessionHandler().getServer();
210 synchronized (server)
211 {
212 _sessionIdManager=server.getSessionIdManager();
213 if (_sessionIdManager==null)
214 {
215 _sessionIdManager=new HashSessionIdManager();
216 server.setSessionIdManager(_sessionIdManager);
217 }
218 }
219 }
220 if (!_sessionIdManager.isStarted())
221 _sessionIdManager.start();
222
223
224 if (_context!=null)
225 {
226 String tmp=_context.getInitParameter(SessionManager.__SessionCookieProperty);
227 if (tmp!=null)
228 _sessionCookie=tmp;
229
230 tmp=_context.getInitParameter(SessionManager.__SessionIdPathParameterNameProperty);
231 if (tmp!=null)
232 setSessionIdPathParameterName(tmp);
233
234
235 if (_maxCookieAge==-1)
236 {
237 tmp=_context.getInitParameter(SessionManager.__MaxAgeProperty);
238 if (tmp!=null)
239 _maxCookieAge=Integer.parseInt(tmp.trim());
240 }
241
242
243 if (_sessionDomain==null)
244 _sessionDomain=_context.getInitParameter(SessionManager.__SessionDomainProperty);
245
246
247 if (_sessionPath==null)
248 _sessionPath=_context.getInitParameter(SessionManager.__SessionPathProperty);
249
250 tmp=_context.getInitParameter(SessionManager.__CheckRemoteSessionEncoding);
251 if (tmp!=null)
252 _checkingRemoteSessionIdEncoding=Boolean.parseBoolean(tmp);
253 }
254
255 super.doStart();
256 }
257
258
259 @Override
260 public void doStop() throws Exception
261 {
262 super.doStop();
263
264 invalidateSessions();
265
266 _loader=null;
267 }
268
269
270
271
272
273 public boolean getHttpOnly()
274 {
275 return _httpOnly;
276 }
277
278
279 public HttpSession getHttpSession(String nodeId)
280 {
281 String cluster_id = getSessionIdManager().getClusterId(nodeId);
282
283 AbstractSession session = getSession(cluster_id);
284 if (session!=null && !session.getNodeId().equals(nodeId))
285 session.setIdChanged(true);
286 return session;
287 }
288
289
290
291
292
293
294 public SessionIdManager getIdManager()
295 {
296 return getSessionIdManager();
297 }
298
299
300
301
302
303 public SessionIdManager getSessionIdManager()
304 {
305 return _sessionIdManager;
306 }
307
308
309 public int getMaxCookieAge()
310 {
311 return _maxCookieAge;
312 }
313
314
315
316
317
318 public int getMaxInactiveInterval()
319 {
320 return _dftMaxIdleSecs;
321 }
322
323
324
325
326
327 @Deprecated
328 public int getMaxSessions()
329 {
330 return getSessionsMax();
331 }
332
333
334
335
336
337 public int getSessionsMax()
338 {
339 return (int)_sessionsStats.getMax();
340 }
341
342
343
344
345
346 public int getSessionsTotal()
347 {
348 return (int)_sessionsStats.getTotal();
349 }
350
351
352
353
354
355 @Deprecated
356 public SessionIdManager getMetaManager()
357 {
358 return getSessionIdManager();
359 }
360
361
362
363
364
365 @Deprecated
366 public int getMinSessions()
367 {
368 return 0;
369 }
370
371
372 public int getRefreshCookieAge()
373 {
374 return _refreshCookieAge;
375 }
376
377
378
379
380
381
382 public boolean getSecureCookies()
383 {
384 return _secureCookies;
385 }
386
387
388 public String getSessionCookie()
389 {
390 return _sessionCookie;
391 }
392
393
394 public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)
395 {
396 if (isUsingCookies())
397 {
398 String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath;
399 sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath;
400 String id = getNodeId(session);
401 HttpCookie cookie=new HttpCookie(
402 _sessionCookie,
403 id,
404 _sessionDomain,
405 sessionPath,
406 getMaxCookieAge(),
407 getHttpOnly(),
408 requestIsSecure&&getSecureCookies());
409
410 return cookie;
411 }
412 return null;
413 }
414
415 public String getSessionDomain()
416 {
417 return _sessionDomain;
418 }
419
420
421
422
423
424 public SessionHandler getSessionHandler()
425 {
426 return _sessionHandler;
427 }
428
429
430
431
432
433 @SuppressWarnings("rawtypes")
434 public Map getSessionMap()
435 {
436 throw new UnsupportedOperationException();
437 }
438
439
440 public String getSessionPath()
441 {
442 return _sessionPath;
443 }
444
445
446 public int getSessions()
447 {
448 return (int)_sessionsStats.getCurrent();
449 }
450
451
452 public String getSessionIdPathParameterName()
453 {
454 return _sessionIdPathParameterName;
455 }
456
457
458 public String getSessionIdPathParameterNamePrefix()
459 {
460 return _sessionIdPathParameterNamePrefix;
461 }
462
463
464
465
466
467 public boolean isUsingCookies()
468 {
469 return _usingCookies;
470 }
471
472
473 public boolean isValid(HttpSession session)
474 {
475 AbstractSession s = ((SessionIf)session).getSession();
476 return s.isValid();
477 }
478
479
480 public String getClusterId(HttpSession session)
481 {
482 AbstractSession s = ((SessionIf)session).getSession();
483 return s.getClusterId();
484 }
485
486
487 public String getNodeId(HttpSession session)
488 {
489 AbstractSession s = ((SessionIf)session).getSession();
490 return s.getNodeId();
491 }
492
493
494
495
496
497 public HttpSession newHttpSession(HttpServletRequest request)
498 {
499 AbstractSession session=newSession(request);
500 session.setMaxInactiveInterval(_dftMaxIdleSecs);
501 addSession(session,true);
502 return session;
503 }
504
505
506 public void removeEventListener(EventListener listener)
507 {
508 if (listener instanceof HttpSessionAttributeListener)
509 _sessionAttributeListeners.remove(listener);
510 if (listener instanceof HttpSessionListener)
511 _sessionListeners.remove(listener);
512 }
513
514
515
516
517
518 @Deprecated
519 public void resetStats()
520 {
521 statsReset();
522 }
523
524
525
526
527
528 public void statsReset()
529 {
530 _sessionsStats.reset(getSessions());
531 _sessionTimeStats.reset();
532 }
533
534
535
536
537
538
539 public void setHttpOnly(boolean httpOnly)
540 {
541 _httpOnly=httpOnly;
542 }
543
544
545
546
547
548
549 public void setIdManager(SessionIdManager metaManager)
550 {
551 setSessionIdManager(metaManager);
552 }
553
554
555
556
557
558 public void setSessionIdManager(SessionIdManager metaManager)
559 {
560 _sessionIdManager=metaManager;
561 }
562
563
564 public void setMaxCookieAge(int maxCookieAgeInSeconds)
565 {
566 _maxCookieAge=maxCookieAgeInSeconds;
567
568 if (_maxCookieAge>0 && _refreshCookieAge==0)
569 _refreshCookieAge=_maxCookieAge/3;
570
571 }
572
573
574
575
576
577 public void setMaxInactiveInterval(int seconds)
578 {
579 _dftMaxIdleSecs=seconds;
580 }
581
582
583
584
585
586 @Deprecated
587 public void setMetaManager(SessionIdManager metaManager)
588 {
589 setSessionIdManager(metaManager);
590 }
591
592
593 public void setRefreshCookieAge(int ageInSeconds)
594 {
595 _refreshCookieAge=ageInSeconds;
596 }
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613 public void setSecureCookies(boolean secureCookies)
614 {
615 _secureCookies=secureCookies;
616 }
617
618 public void setSessionCookie(String cookieName)
619 {
620 _sessionCookie=cookieName;
621 }
622
623 public void setSessionDomain(String domain)
624 {
625 _sessionDomain=domain;
626 }
627
628
629
630
631
632
633 public void setSessionHandler(SessionHandler sessionHandler)
634 {
635 _sessionHandler=sessionHandler;
636 }
637
638
639
640
641
642 public void setSessionPath(String path)
643 {
644 _sessionPath=path;
645 }
646
647
648 public void setSessionIdPathParameterName(String param)
649 {
650 _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param;
651 _sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"=");
652 }
653
654
655
656
657
658 public void setUsingCookies(boolean usingCookies)
659 {
660 _usingCookies=usingCookies;
661 }
662
663
664 protected abstract void addSession(AbstractSession session);
665
666
667
668
669
670
671 protected void addSession(AbstractSession session, boolean created)
672 {
673 synchronized (_sessionIdManager)
674 {
675 _sessionIdManager.addSession(session);
676 addSession(session);
677 }
678
679 if (created)
680 {
681 _sessionsStats.increment();
682 if (_sessionListeners!=null)
683 {
684 HttpSessionEvent event=new HttpSessionEvent(session);
685 for (HttpSessionListener listener : _sessionListeners)
686 listener.sessionCreated(event);
687 }
688 }
689 }
690
691
692
693
694
695
696
697 public abstract AbstractSession getSession(String idInCluster);
698
699 protected abstract void invalidateSessions() throws Exception;
700
701
702
703
704
705
706
707
708 protected abstract AbstractSession newSession(HttpServletRequest request);
709
710
711
712
713
714
715 public boolean isNodeIdInSessionId()
716 {
717 return _nodeIdInSessionId;
718 }
719
720
721
722
723
724 public void setNodeIdInSessionId(boolean nodeIdInSessionId)
725 {
726 _nodeIdInSessionId=nodeIdInSessionId;
727 }
728
729
730
731
732
733
734
735 public void removeSession(HttpSession session, boolean invalidate)
736 {
737 AbstractSession s = ((SessionIf)session).getSession();
738 removeSession(s,invalidate);
739 }
740
741
742
743
744
745
746
747 public void removeSession(AbstractSession session, boolean invalidate)
748 {
749
750 boolean removed = removeSession(session.getClusterId());
751
752 if (removed)
753 {
754 _sessionsStats.decrement();
755 _sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0));
756
757
758 _sessionIdManager.removeSession(session);
759 if (invalidate)
760 _sessionIdManager.invalidateAll(session.getClusterId());
761
762 if (invalidate && _sessionListeners!=null)
763 {
764 HttpSessionEvent event=new HttpSessionEvent(session);
765 for (HttpSessionListener listener : _sessionListeners)
766 listener.sessionDestroyed(event);
767 }
768 }
769 }
770
771
772 protected abstract boolean removeSession(String idInCluster);
773
774
775
776
777
778 public long getSessionTimeMax()
779 {
780 return _sessionTimeStats.getMax();
781 }
782
783
784
785
786
787 public long getSessionTimeTotal()
788 {
789 return _sessionTimeStats.getTotal();
790 }
791
792
793
794
795
796 public double getSessionTimeMean()
797 {
798 return _sessionTimeStats.getMean();
799 }
800
801
802
803
804
805 public double getSessionTimeStdDev()
806 {
807 return _sessionTimeStats.getStdDev();
808 }
809
810
811
812
813
814 public boolean isCheckingRemoteSessionIdEncoding()
815 {
816 return _checkingRemoteSessionIdEncoding;
817 }
818
819
820
821
822
823 public void setCheckingRemoteSessionIdEncoding(boolean remote)
824 {
825 _checkingRemoteSessionIdEncoding=remote;
826 }
827
828
829
830
831
832
833
834
835
836 public interface SessionIf extends HttpSession
837 {
838 public AbstractSession getSession();
839 }
840
841 public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)
842 {
843 if (!_sessionAttributeListeners.isEmpty())
844 {
845 HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old);
846
847 for (HttpSessionAttributeListener l : _sessionAttributeListeners)
848 {
849 if (old==null)
850 l.attributeAdded(event);
851 else if (value==null)
852 l.attributeRemoved(event);
853 else
854 l.attributeReplaced(event);
855 }
856 }
857 }
858 }