目的:多个应用之间 Session 共享
方法一 ServletContext 这是网上最容易搜到的方法,其实是完全错误的
https://blog.youkuaiyun.com/u014756827/article/details/52597549#
初看这个方法,好像是完成我们的目标,可是在实际应用时发现一个问题,就是当 user1 在登录前不可以进入 web1 应用,在 user1 登录后才可以进入web1 应用,但是当user1退出之后,未登录的用户依然可以进入 web1 应用。
后来仔细看了一下网上提供的方法,它只是在webappA的ServletContext存储了一个session值,然后传递给 web2 ,但是也仅仅只能传递一个session值,如果有两个用户的时候就会出现session覆盖。
方法二 sessionCookiePath
在tomcat conf/context.html中有如下配置
- sessionCookieName
The name to be used for all session cookies created for this context. If set, this overrides any name set by the web application. If not set, the value specified by the web application, if any, will be used, or the name JSESSIONID if the web application does not explicitly set one. - sessionCookiePath
The path to be used for all session cookies created for this context. If set, this overrides any path set by the web application. If not set, the value specified by the web application will be used, or the context path used if the web application does not explicitly set one. To configure all web application to use an empty path (this can be useful for portlet specification implementations) set this attribute to / in the global CATALINA_BASE/conf/context.xml file.
Note: Once one web application using sessionCookiePath="/" obtains a session, all subsequent sessions for any other web application in the same host also configured with sessionCookiePath="/" will always use the same session ID. This holds even if the session is invalidated and a new one created. This makes session fixation protection more difficult and requires custom, Tomcat specific code to change the session ID shared by the multiple applications.
也就是说我们可以通过sessionCookiePath属性使得一个tomcat实例下所有的webapps都共享一个session,通过sessionCookieName来指定sessionCookieName名字。
于是我就在tomcat conf/context.html中配置如下:
<Context sessionCookiePath="/" sessionCookieName="SESSIONID" >
</Context>
然后在进行测试,发现在 web2 应用和 web1 应用中确实sessionCookie是一样的。可是当我在 web2 中进行session.setAttribute();时,web1 应用不能从session中取得值,为null,也就是说,对 web1 应用而言,web2 应用在session所储存的值是不可见的。然后在 web1 session中进行session.setAttribute();, web2 应用总同样无法取得 web1 存储在session中的数据,猜想可能是不同的webapps并不会共享相同的session内存,每一个webapps维护自己session HashTable,后来了解到 session管理器是和context容器关联的,也就说每个web应用都会有一个session管理器,所以 web1 应用当然无法从 web2 应用存储的session中取值。
方法三 redis session 共享
其实只需要在方法二的基础上共享 session 即可,使用 redis 配置
在tomcat conf/context.html中配置如下:
<Context sessionCookiePath="/" sessionCookieName="SESSIONID" >
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="192.168.0.23"
port="6379"
database="0"
maxInactiveInterval="60" />
</Context>
然后即可实现tomcat中session在两个webapp中实现共享。
方法四 spring-session
spring-session中通过自己生成session并且存储到redis中,还是需要设置sessionCookiePath="/"(在一个tomcat两个应用需要单点登录的情况),其他session共享方案(在多个tomcat中实现单点登录可以参考 spring session无法实现共享(多web应用)),但是spring-session不是服务器级别的,而是web 应用级别的,不受服务器如tomcat,jetty,jboss的限制。