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