1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.server.session; 20 21 import static java.lang.Math.round; 22 23 import java.util.Arrays; 24 import java.util.Collections; 25 import java.util.Enumeration; 26 import java.util.EventListener; 27 import java.util.HashSet; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 import java.util.concurrent.CopyOnWriteArrayList; 33 34 import javax.servlet.ServletRequest; 35 import javax.servlet.SessionCookieConfig; 36 import javax.servlet.SessionTrackingMode; 37 import javax.servlet.http.HttpServletRequest; 38 import javax.servlet.http.HttpSession; 39 import javax.servlet.http.HttpSessionAttributeListener; 40 import javax.servlet.http.HttpSessionBindingEvent; 41 import javax.servlet.http.HttpSessionContext; 42 import javax.servlet.http.HttpSessionEvent; 43 import javax.servlet.http.HttpSessionListener; 44 45 import org.eclipse.jetty.http.HttpCookie; 46 import org.eclipse.jetty.server.AbstractConnector; 47 import org.eclipse.jetty.server.Request; 48 import org.eclipse.jetty.server.Server; 49 import org.eclipse.jetty.server.SessionIdManager; 50 import org.eclipse.jetty.server.SessionManager; 51 import org.eclipse.jetty.server.handler.ContextHandler; 52 import org.eclipse.jetty.util.component.AbstractLifeCycle; 53 import org.eclipse.jetty.util.log.Logger; 54 import org.eclipse.jetty.util.statistic.CounterStatistic; 55 import org.eclipse.jetty.util.statistic.SampleStatistic; 56 57 /* ------------------------------------------------------------ */ 58 /** 59 * An Abstract implementation of SessionManager. The partial implementation of 60 * SessionManager interface provides the majority of the handling required to 61 * implement a SessionManager. Concrete implementations of SessionManager based 62 * on AbstractSessionManager need only implement the newSession method to return 63 * a specialised version of the Session inner class that provides an attribute 64 * Map. 65 * <p> 66 */ 67 @SuppressWarnings("deprecation") 68 public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager 69 { 70 final static Logger __log = SessionHandler.LOG; 71 72 public Set<SessionTrackingMode> __defaultSessionTrackingModes = 73 Collections.unmodifiableSet( 74 new HashSet<SessionTrackingMode>( 75 Arrays.asList(new SessionTrackingMode[]{SessionTrackingMode.COOKIE,SessionTrackingMode.URL}))); 76 77 public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated"; 78 79 /* ------------------------------------------------------------ */ 80 public final static int __distantFuture=60*60*24*7*52*20; 81 82 static final HttpSessionContext __nullSessionContext=new HttpSessionContext() 83 { 84 public HttpSession getSession(String sessionId) 85 { 86 return null; 87 } 88 89 @SuppressWarnings({ "rawtypes", "unchecked" }) 90 public Enumeration getIds() 91 { 92 return Collections.enumeration(Collections.EMPTY_LIST); 93 } 94 }; 95 96 private boolean _usingCookies=true; 97 98 /* ------------------------------------------------------------ */ 99 // Setting of max inactive interval for new sessions 100 // -1 means no timeout 101 protected int _dftMaxIdleSecs=-1; 102 protected SessionHandler _sessionHandler; 103 protected boolean _httpOnly=false; 104 protected SessionIdManager _sessionIdManager; 105 protected boolean _secureCookies=false; 106 protected boolean _secureRequestOnly=true; 107 108 protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>(); 109 protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>(); 110 111 protected ClassLoader _loader; 112 protected ContextHandler.Context _context; 113 protected String _sessionCookie=__DefaultSessionCookie; 114 protected String _sessionIdPathParameterName = __DefaultSessionIdPathParameterName; 115 protected String _sessionIdPathParameterNamePrefix =";"+ _sessionIdPathParameterName +"="; 116 protected String _sessionDomain; 117 protected String _sessionPath; 118 protected int _maxCookieAge=-1; 119 protected int _refreshCookieAge; 120 protected boolean _nodeIdInSessionId; 121 protected boolean _checkingRemoteSessionIdEncoding; 122 protected String _sessionComment; 123 124 public Set<SessionTrackingMode> _sessionTrackingModes; 125 126 private boolean _usingURLs; 127 128 protected final CounterStatistic _sessionsStats = new CounterStatistic(); 129 protected final SampleStatistic _sessionTimeStats = new SampleStatistic(); 130 131 132 /* ------------------------------------------------------------ */ renewSession(HttpServletRequest request, HttpSession httpSession, boolean authenticated)133 public static HttpSession renewSession (HttpServletRequest request, HttpSession httpSession, boolean authenticated) 134 { 135 Map<String,Object> attributes = new HashMap<String, Object>(); 136 137 for (Enumeration<String> e=httpSession.getAttributeNames();e.hasMoreElements();) 138 { 139 String name=e.nextElement(); 140 attributes.put(name,httpSession.getAttribute(name)); 141 httpSession.removeAttribute(name); 142 } 143 144 httpSession.invalidate(); 145 httpSession = request.getSession(true); 146 if (authenticated) 147 httpSession.setAttribute(SESSION_KNOWN_ONLY_TO_AUTHENTICATED, Boolean.TRUE); 148 for (Map.Entry<String, Object> entry: attributes.entrySet()) 149 httpSession.setAttribute(entry.getKey(),entry.getValue()); 150 return httpSession; 151 } 152 153 /* ------------------------------------------------------------ */ AbstractSessionManager()154 public AbstractSessionManager() 155 { 156 setSessionTrackingModes(__defaultSessionTrackingModes); 157 } 158 159 /* ------------------------------------------------------------ */ getContext()160 public ContextHandler.Context getContext() 161 { 162 return _context; 163 } 164 165 /* ------------------------------------------------------------ */ getContextHandler()166 public ContextHandler getContextHandler() 167 { 168 return _context.getContextHandler(); 169 } 170 getSessionPath()171 public String getSessionPath() 172 { 173 return _sessionPath; 174 } 175 getMaxCookieAge()176 public int getMaxCookieAge() 177 { 178 return _maxCookieAge; 179 } 180 181 /* ------------------------------------------------------------ */ access(HttpSession session,boolean secure)182 public HttpCookie access(HttpSession session,boolean secure) 183 { 184 long now=System.currentTimeMillis(); 185 186 AbstractSession s = ((SessionIf)session).getSession(); 187 188 if (s.access(now)) 189 { 190 // Do we need to refresh the cookie? 191 if (isUsingCookies() && 192 (s.isIdChanged() || 193 (getSessionCookieConfig().getMaxAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge())) 194 ) 195 ) 196 { 197 HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure); 198 s.cookieSet(); 199 s.setIdChanged(false); 200 return cookie; 201 } 202 } 203 return null; 204 } 205 206 /* ------------------------------------------------------------ */ addEventListener(EventListener listener)207 public void addEventListener(EventListener listener) 208 { 209 if (listener instanceof HttpSessionAttributeListener) 210 _sessionAttributeListeners.add((HttpSessionAttributeListener)listener); 211 if (listener instanceof HttpSessionListener) 212 _sessionListeners.add((HttpSessionListener)listener); 213 } 214 215 /* ------------------------------------------------------------ */ clearEventListeners()216 public void clearEventListeners() 217 { 218 _sessionAttributeListeners.clear(); 219 _sessionListeners.clear(); 220 } 221 222 /* ------------------------------------------------------------ */ complete(HttpSession session)223 public void complete(HttpSession session) 224 { 225 AbstractSession s = ((SessionIf)session).getSession(); 226 s.complete(); 227 } 228 229 /* ------------------------------------------------------------ */ 230 @Override doStart()231 public void doStart() throws Exception 232 { 233 _context=ContextHandler.getCurrentContext(); 234 _loader=Thread.currentThread().getContextClassLoader(); 235 236 if (_sessionIdManager==null) 237 { 238 final Server server=getSessionHandler().getServer(); 239 synchronized (server) 240 { 241 _sessionIdManager=server.getSessionIdManager(); 242 if (_sessionIdManager==null) 243 { 244 _sessionIdManager=new HashSessionIdManager(); 245 server.setSessionIdManager(_sessionIdManager); 246 } 247 } 248 } 249 if (!_sessionIdManager.isStarted()) 250 _sessionIdManager.start(); 251 252 // Look for a session cookie name 253 if (_context!=null) 254 { 255 String tmp=_context.getInitParameter(SessionManager.__SessionCookieProperty); 256 if (tmp!=null) 257 _sessionCookie=tmp; 258 259 tmp=_context.getInitParameter(SessionManager.__SessionIdPathParameterNameProperty); 260 if (tmp!=null) 261 setSessionIdPathParameterName(tmp); 262 263 // set up the max session cookie age if it isn't already 264 if (_maxCookieAge==-1) 265 { 266 tmp=_context.getInitParameter(SessionManager.__MaxAgeProperty); 267 if (tmp!=null) 268 _maxCookieAge=Integer.parseInt(tmp.trim()); 269 } 270 271 // set up the session domain if it isn't already 272 if (_sessionDomain==null) 273 _sessionDomain=_context.getInitParameter(SessionManager.__SessionDomainProperty); 274 275 // set up the sessionPath if it isn't already 276 if (_sessionPath==null) 277 _sessionPath=_context.getInitParameter(SessionManager.__SessionPathProperty); 278 279 tmp=_context.getInitParameter(SessionManager.__CheckRemoteSessionEncoding); 280 if (tmp!=null) 281 _checkingRemoteSessionIdEncoding=Boolean.parseBoolean(tmp); 282 } 283 284 super.doStart(); 285 } 286 287 /* ------------------------------------------------------------ */ 288 @Override doStop()289 public void doStop() throws Exception 290 { 291 super.doStop(); 292 293 invalidateSessions(); 294 295 _loader=null; 296 } 297 298 /* ------------------------------------------------------------ */ 299 /** 300 * @return Returns the httpOnly. 301 */ getHttpOnly()302 public boolean getHttpOnly() 303 { 304 return _httpOnly; 305 } 306 307 /* ------------------------------------------------------------ */ getHttpSession(String nodeId)308 public HttpSession getHttpSession(String nodeId) 309 { 310 String cluster_id = getSessionIdManager().getClusterId(nodeId); 311 312 AbstractSession session = getSession(cluster_id); 313 if (session!=null && !session.getNodeId().equals(nodeId)) 314 session.setIdChanged(true); 315 return session; 316 } 317 318 /* ------------------------------------------------------------ */ 319 /** 320 * @return Returns the metaManager used for cross context session management 321 * @deprecated Use {@link #getSessionIdManager()} 322 */ getIdManager()323 public SessionIdManager getIdManager() 324 { 325 return getSessionIdManager(); 326 } 327 328 /* ------------------------------------------------------------ */ 329 /** 330 * @return Returns the SessionIdManager used for cross context session management 331 */ getSessionIdManager()332 public SessionIdManager getSessionIdManager() 333 { 334 return _sessionIdManager; 335 } 336 337 338 /* ------------------------------------------------------------ */ 339 /** 340 * @return seconds 341 */ 342 @Override getMaxInactiveInterval()343 public int getMaxInactiveInterval() 344 { 345 return _dftMaxIdleSecs; 346 } 347 348 /* ------------------------------------------------------------ */ 349 /** 350 * @see #getSessionsMax() 351 */ 352 @Deprecated getMaxSessions()353 public int getMaxSessions() 354 { 355 return getSessionsMax(); 356 } 357 358 /* ------------------------------------------------------------ */ 359 /** 360 * @return maximum number of sessions 361 */ getSessionsMax()362 public int getSessionsMax() 363 { 364 return (int)_sessionsStats.getMax(); 365 } 366 367 /* ------------------------------------------------------------ */ 368 /** 369 * @return total number of sessions 370 */ getSessionsTotal()371 public int getSessionsTotal() 372 { 373 return (int)_sessionsStats.getTotal(); 374 } 375 376 /* ------------------------------------------------------------ */ 377 /** 378 * @deprecated use {@link #getSessionIdManager()} 379 */ 380 @Deprecated getMetaManager()381 public SessionIdManager getMetaManager() 382 { 383 return getSessionIdManager(); 384 } 385 386 /* ------------------------------------------------------------ */ 387 /** 388 * @deprecated always returns 0. no replacement available. 389 */ 390 @Deprecated getMinSessions()391 public int getMinSessions() 392 { 393 return 0; 394 } 395 396 /* ------------------------------------------------------------ */ getRefreshCookieAge()397 public int getRefreshCookieAge() 398 { 399 return _refreshCookieAge; 400 } 401 402 403 /* ------------------------------------------------------------ */ 404 /** 405 * @return same as SessionCookieConfig.getSecure(). If true, session 406 * cookies are ALWAYS marked as secure. If false, a session cookie is 407 * ONLY marked as secure if _secureRequestOnly == true and it is a HTTPS request. 408 */ getSecureCookies()409 public boolean getSecureCookies() 410 { 411 return _secureCookies; 412 } 413 414 /* ------------------------------------------------------------ */ 415 /** 416 * @return true if session cookie is to be marked as secure only on HTTPS requests 417 */ isSecureRequestOnly()418 public boolean isSecureRequestOnly() 419 { 420 return _secureRequestOnly; 421 } 422 423 424 /* ------------------------------------------------------------ */ 425 /** 426 * @return if true, session cookie will be marked as secure only iff 427 * HTTPS request. Can be overridden by setting SessionCookieConfig.setSecure(true), 428 * in which case the session cookie will be marked as secure on both HTTPS and HTTP. 429 */ setSecureRequestOnly(boolean secureRequestOnly)430 public void setSecureRequestOnly(boolean secureRequestOnly) 431 { 432 _secureRequestOnly = secureRequestOnly; 433 } 434 435 436 437 /* ------------------------------------------------------------ */ getSessionCookie()438 public String getSessionCookie() 439 { 440 return _sessionCookie; 441 } 442 443 /* ------------------------------------------------------------ */ 444 /** 445 * A sessioncookie is marked as secure IFF any of the following conditions are true: 446 * <ol> 447 * <li>SessionCookieConfig.setSecure == true</li> 448 * <li>SessionCookieConfig.setSecure == false && _secureRequestOnly==true && request is HTTPS</li> 449 * </ol> 450 * According to SessionCookieConfig javadoc, case 1 can be used when: 451 * "... even though the request that initiated the session came over HTTP, 452 * is to support a topology where the web container is front-ended by an 453 * SSL offloading load balancer. In this case, the traffic between the client 454 * and the load balancer will be over HTTPS, whereas the traffic between the 455 * load balancer and the web container will be over HTTP." 456 * 457 * For case 2, you can use _secureRequestOnly to determine if you want the 458 * Servlet Spec 3.0 default behaviour when SessionCookieConfig.setSecure==false, 459 * which is: 460 * "they shall be marked as secure only if the request that initiated the 461 * corresponding session was also secure" 462 * 463 * The default for _secureRequestOnly is true, which gives the above behaviour. If 464 * you set it to false, then a session cookie is NEVER marked as secure, even if 465 * the initiating request was secure. 466 * 467 * @see org.eclipse.jetty.server.SessionManager#getSessionCookie(javax.servlet.http.HttpSession, java.lang.String, boolean) 468 */ getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)469 public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure) 470 { 471 if (isUsingCookies()) 472 { 473 String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath; 474 sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath; 475 String id = getNodeId(session); 476 HttpCookie cookie = null; 477 if (_sessionComment == null) 478 { 479 cookie = new HttpCookie( 480 _sessionCookie, 481 id, 482 _sessionDomain, 483 sessionPath, 484 _cookieConfig.getMaxAge(), 485 _cookieConfig.isHttpOnly(), 486 _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure)); 487 } 488 else 489 { 490 cookie = new HttpCookie( 491 _sessionCookie, 492 id, 493 _sessionDomain, 494 sessionPath, 495 _cookieConfig.getMaxAge(), 496 _cookieConfig.isHttpOnly(), 497 _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure), 498 _sessionComment, 499 1); 500 } 501 502 return cookie; 503 } 504 return null; 505 } 506 getSessionDomain()507 public String getSessionDomain() 508 { 509 return _sessionDomain; 510 } 511 512 /* ------------------------------------------------------------ */ 513 /** 514 * @return Returns the sessionHandler. 515 */ getSessionHandler()516 public SessionHandler getSessionHandler() 517 { 518 return _sessionHandler; 519 } 520 521 /* ------------------------------------------------------------ */ 522 /** 523 * @deprecated Need to review if it is needed. 524 */ 525 @SuppressWarnings("rawtypes") getSessionMap()526 public Map getSessionMap() 527 { 528 throw new UnsupportedOperationException(); 529 } 530 531 532 533 /* ------------------------------------------------------------ */ getSessions()534 public int getSessions() 535 { 536 return (int)_sessionsStats.getCurrent(); 537 } 538 539 /* ------------------------------------------------------------ */ getSessionIdPathParameterName()540 public String getSessionIdPathParameterName() 541 { 542 return _sessionIdPathParameterName; 543 } 544 545 /* ------------------------------------------------------------ */ getSessionIdPathParameterNamePrefix()546 public String getSessionIdPathParameterNamePrefix() 547 { 548 return _sessionIdPathParameterNamePrefix; 549 } 550 551 /* ------------------------------------------------------------ */ 552 /** 553 * @return Returns the usingCookies. 554 */ isUsingCookies()555 public boolean isUsingCookies() 556 { 557 return _usingCookies; 558 } 559 560 /* ------------------------------------------------------------ */ isValid(HttpSession session)561 public boolean isValid(HttpSession session) 562 { 563 AbstractSession s = ((SessionIf)session).getSession(); 564 return s.isValid(); 565 } 566 567 /* ------------------------------------------------------------ */ getClusterId(HttpSession session)568 public String getClusterId(HttpSession session) 569 { 570 AbstractSession s = ((SessionIf)session).getSession(); 571 return s.getClusterId(); 572 } 573 574 /* ------------------------------------------------------------ */ getNodeId(HttpSession session)575 public String getNodeId(HttpSession session) 576 { 577 AbstractSession s = ((SessionIf)session).getSession(); 578 return s.getNodeId(); 579 } 580 581 /* ------------------------------------------------------------ */ 582 /** 583 * Create a new HttpSession for a request 584 */ newHttpSession(HttpServletRequest request)585 public HttpSession newHttpSession(HttpServletRequest request) 586 { 587 AbstractSession session=newSession(request); 588 session.setMaxInactiveInterval(_dftMaxIdleSecs); 589 addSession(session,true); 590 return session; 591 } 592 593 /* ------------------------------------------------------------ */ removeEventListener(EventListener listener)594 public void removeEventListener(EventListener listener) 595 { 596 if (listener instanceof HttpSessionAttributeListener) 597 _sessionAttributeListeners.remove(listener); 598 if (listener instanceof HttpSessionListener) 599 _sessionListeners.remove(listener); 600 } 601 602 /* ------------------------------------------------------------ */ 603 /** 604 * @see #statsReset() 605 */ 606 @Deprecated resetStats()607 public void resetStats() 608 { 609 statsReset(); 610 } 611 612 /* ------------------------------------------------------------ */ 613 /** 614 * Reset statistics values 615 */ statsReset()616 public void statsReset() 617 { 618 _sessionsStats.reset(getSessions()); 619 _sessionTimeStats.reset(); 620 } 621 622 /* ------------------------------------------------------------ */ 623 /** 624 * @param httpOnly 625 * The httpOnly to set. 626 */ setHttpOnly(boolean httpOnly)627 public void setHttpOnly(boolean httpOnly) 628 { 629 _httpOnly=httpOnly; 630 } 631 632 /* ------------------------------------------------------------ */ 633 /** 634 * @param metaManager The metaManager used for cross context session management. 635 * @deprecated use {@link #setSessionIdManager(SessionIdManager)} 636 */ setIdManager(SessionIdManager metaManager)637 public void setIdManager(SessionIdManager metaManager) 638 { 639 setSessionIdManager(metaManager); 640 } 641 642 /* ------------------------------------------------------------ */ 643 /** 644 * @param metaManager The metaManager used for cross context session management. 645 */ setSessionIdManager(SessionIdManager metaManager)646 public void setSessionIdManager(SessionIdManager metaManager) 647 { 648 _sessionIdManager=metaManager; 649 } 650 651 652 653 /* ------------------------------------------------------------ */ 654 /** 655 * @param seconds 656 */ setMaxInactiveInterval(int seconds)657 public void setMaxInactiveInterval(int seconds) 658 { 659 _dftMaxIdleSecs=seconds; 660 } 661 662 663 /* ------------------------------------------------------------ */ setRefreshCookieAge(int ageInSeconds)664 public void setRefreshCookieAge(int ageInSeconds) 665 { 666 _refreshCookieAge=ageInSeconds; 667 } 668 669 670 setSessionCookie(String cookieName)671 public void setSessionCookie(String cookieName) 672 { 673 _sessionCookie=cookieName; 674 } 675 676 677 678 /* ------------------------------------------------------------ */ 679 /** 680 * @param sessionHandler 681 * The sessionHandler to set. 682 */ setSessionHandler(SessionHandler sessionHandler)683 public void setSessionHandler(SessionHandler sessionHandler) 684 { 685 _sessionHandler=sessionHandler; 686 } 687 688 689 /* ------------------------------------------------------------ */ setSessionIdPathParameterName(String param)690 public void setSessionIdPathParameterName(String param) 691 { 692 _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param; 693 _sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"="); 694 } 695 /* ------------------------------------------------------------ */ 696 /** 697 * @param usingCookies 698 * The usingCookies to set. 699 */ setUsingCookies(boolean usingCookies)700 public void setUsingCookies(boolean usingCookies) 701 { 702 _usingCookies=usingCookies; 703 } 704 705 addSession(AbstractSession session)706 protected abstract void addSession(AbstractSession session); 707 708 /* ------------------------------------------------------------ */ 709 /** 710 * Add the session Registers the session with this manager and registers the 711 * session ID with the sessionIDManager; 712 */ addSession(AbstractSession session, boolean created)713 protected void addSession(AbstractSession session, boolean created) 714 { 715 synchronized (_sessionIdManager) 716 { 717 _sessionIdManager.addSession(session); 718 addSession(session); 719 } 720 721 if (created) 722 { 723 _sessionsStats.increment(); 724 if (_sessionListeners!=null) 725 { 726 HttpSessionEvent event=new HttpSessionEvent(session); 727 for (HttpSessionListener listener : _sessionListeners) 728 listener.sessionCreated(event); 729 } 730 } 731 } 732 733 /* ------------------------------------------------------------ */ 734 /** 735 * Get a known existing session 736 * @param idInCluster The session ID in the cluster, stripped of any worker name. 737 * @return A Session or null if none exists. 738 */ getSession(String idInCluster)739 public abstract AbstractSession getSession(String idInCluster); 740 invalidateSessions()741 protected abstract void invalidateSessions() throws Exception; 742 743 744 /* ------------------------------------------------------------ */ 745 /** 746 * Create a new session instance 747 * @param request 748 * @return the new session 749 */ newSession(HttpServletRequest request)750 protected abstract AbstractSession newSession(HttpServletRequest request); 751 752 753 /* ------------------------------------------------------------ */ 754 /** 755 * @return true if the cluster node id (worker id) is returned as part of the session id by {@link HttpSession#getId()}. Default is false. 756 */ isNodeIdInSessionId()757 public boolean isNodeIdInSessionId() 758 { 759 return _nodeIdInSessionId; 760 } 761 762 /* ------------------------------------------------------------ */ 763 /** 764 * @param nodeIdInSessionId true if the cluster node id (worker id) will be returned as part of the session id by {@link HttpSession#getId()}. Default is false. 765 */ setNodeIdInSessionId(boolean nodeIdInSessionId)766 public void setNodeIdInSessionId(boolean nodeIdInSessionId) 767 { 768 _nodeIdInSessionId=nodeIdInSessionId; 769 } 770 771 /* ------------------------------------------------------------ */ 772 /** Remove session from manager 773 * @param session The session to remove 774 * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and 775 * {@link SessionIdManager#invalidateAll(String)} should be called. 776 */ removeSession(HttpSession session, boolean invalidate)777 public void removeSession(HttpSession session, boolean invalidate) 778 { 779 AbstractSession s = ((SessionIf)session).getSession(); 780 removeSession(s,invalidate); 781 } 782 783 /* ------------------------------------------------------------ */ 784 /** Remove session from manager 785 * @param session The session to remove 786 * @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and 787 * {@link SessionIdManager#invalidateAll(String)} should be called. 788 */ removeSession(AbstractSession session, boolean invalidate)789 public void removeSession(AbstractSession session, boolean invalidate) 790 { 791 // Remove session from context and global maps 792 boolean removed = removeSession(session.getClusterId()); 793 794 if (removed) 795 { 796 _sessionsStats.decrement(); 797 _sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0)); 798 799 // Remove session from all context and global id maps 800 _sessionIdManager.removeSession(session); 801 if (invalidate) 802 _sessionIdManager.invalidateAll(session.getClusterId()); 803 804 if (invalidate && _sessionListeners!=null) 805 { 806 HttpSessionEvent event=new HttpSessionEvent(session); 807 for (HttpSessionListener listener : _sessionListeners) 808 listener.sessionDestroyed(event); 809 } 810 } 811 } 812 813 /* ------------------------------------------------------------ */ removeSession(String idInCluster)814 protected abstract boolean removeSession(String idInCluster); 815 816 /* ------------------------------------------------------------ */ 817 /** 818 * @return maximum amount of time session remained valid 819 */ getSessionTimeMax()820 public long getSessionTimeMax() 821 { 822 return _sessionTimeStats.getMax(); 823 } 824 825 /* ------------------------------------------------------------ */ getDefaultSessionTrackingModes()826 public Set<SessionTrackingMode> getDefaultSessionTrackingModes() 827 { 828 return __defaultSessionTrackingModes; 829 } 830 831 /* ------------------------------------------------------------ */ getEffectiveSessionTrackingModes()832 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() 833 { 834 return Collections.unmodifiableSet(_sessionTrackingModes); 835 } 836 837 /* ------------------------------------------------------------ */ 838 @Override setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)839 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) 840 { 841 _sessionTrackingModes=new HashSet<SessionTrackingMode>(sessionTrackingModes); 842 _usingCookies=_sessionTrackingModes.contains(SessionTrackingMode.COOKIE); 843 _usingURLs=_sessionTrackingModes.contains(SessionTrackingMode.URL); 844 } 845 846 /* ------------------------------------------------------------ */ 847 @Override isUsingURLs()848 public boolean isUsingURLs() 849 { 850 return _usingURLs; 851 } 852 853 854 /* ------------------------------------------------------------ */ getSessionCookieConfig()855 public SessionCookieConfig getSessionCookieConfig() 856 { 857 return _cookieConfig; 858 } 859 860 /* ------------------------------------------------------------ */ 861 private SessionCookieConfig _cookieConfig = 862 new SessionCookieConfig() 863 { 864 @Override 865 public String getComment() 866 { 867 return _sessionComment; 868 } 869 870 @Override 871 public String getDomain() 872 { 873 return _sessionDomain; 874 } 875 876 @Override 877 public int getMaxAge() 878 { 879 return _maxCookieAge; 880 } 881 882 @Override 883 public String getName() 884 { 885 return _sessionCookie; 886 } 887 888 @Override 889 public String getPath() 890 { 891 return _sessionPath; 892 } 893 894 @Override 895 public boolean isHttpOnly() 896 { 897 return _httpOnly; 898 } 899 900 @Override 901 public boolean isSecure() 902 { 903 return _secureCookies; 904 } 905 906 @Override 907 public void setComment(String comment) 908 { 909 _sessionComment = comment; 910 } 911 912 @Override 913 public void setDomain(String domain) 914 { 915 _sessionDomain=domain; 916 } 917 918 @Override 919 public void setHttpOnly(boolean httpOnly) 920 { 921 _httpOnly=httpOnly; 922 } 923 924 @Override 925 public void setMaxAge(int maxAge) 926 { 927 _maxCookieAge=maxAge; 928 } 929 930 @Override 931 public void setName(String name) 932 { 933 _sessionCookie=name; 934 } 935 936 @Override 937 public void setPath(String path) 938 { 939 _sessionPath=path; 940 } 941 942 @Override 943 public void setSecure(boolean secure) 944 { 945 _secureCookies=secure; 946 } 947 948 }; 949 950 951 /* ------------------------------------------------------------ */ 952 /** 953 * @return total amount of time all sessions remained valid 954 */ getSessionTimeTotal()955 public long getSessionTimeTotal() 956 { 957 return _sessionTimeStats.getTotal(); 958 } 959 960 /* ------------------------------------------------------------ */ 961 /** 962 * @return mean amount of time session remained valid 963 */ getSessionTimeMean()964 public double getSessionTimeMean() 965 { 966 return _sessionTimeStats.getMean(); 967 } 968 969 /* ------------------------------------------------------------ */ 970 /** 971 * @return standard deviation of amount of time session remained valid 972 */ getSessionTimeStdDev()973 public double getSessionTimeStdDev() 974 { 975 return _sessionTimeStats.getStdDev(); 976 } 977 978 /* ------------------------------------------------------------ */ 979 /** 980 * @see org.eclipse.jetty.server.SessionManager#isCheckingRemoteSessionIdEncoding() 981 */ isCheckingRemoteSessionIdEncoding()982 public boolean isCheckingRemoteSessionIdEncoding() 983 { 984 return _checkingRemoteSessionIdEncoding; 985 } 986 987 /* ------------------------------------------------------------ */ 988 /** 989 * @see org.eclipse.jetty.server.SessionManager#setCheckingRemoteSessionIdEncoding(boolean) 990 */ setCheckingRemoteSessionIdEncoding(boolean remote)991 public void setCheckingRemoteSessionIdEncoding(boolean remote) 992 { 993 _checkingRemoteSessionIdEncoding=remote; 994 } 995 996 /* ------------------------------------------------------------ */ 997 /* ------------------------------------------------------------ */ 998 /* ------------------------------------------------------------ */ 999 /** 1000 * Interface that any session wrapper should implement so that 1001 * SessionManager may access the Jetty session implementation. 1002 * 1003 */ 1004 public interface SessionIf extends HttpSession 1005 { getSession()1006 public AbstractSession getSession(); 1007 } 1008 doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)1009 public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value) 1010 { 1011 if (!_sessionAttributeListeners.isEmpty()) 1012 { 1013 HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old); 1014 1015 for (HttpSessionAttributeListener l : _sessionAttributeListeners) 1016 { 1017 if (old==null) 1018 l.attributeAdded(event); 1019 else if (value==null) 1020 l.attributeRemoved(event); 1021 else 1022 l.attributeReplaced(event); 1023 } 1024 } 1025 } 1026 } 1027