關於spring session redis共享session的跨子域的處理
安裝完redis, spring端只要下面這兩個bean配置上就可以用了
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml
version= "1.0" encoding= "UTF-8" ?>
<beans
xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context= "http://www.springframework.org/schema/context" xmlns:p= "http://www.springframework.org/schema/p"
xsi:schemaLocation="http: //www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http: //www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean class = "org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />
<bean
id= "jedisConnectionFactory" class = "org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<property
name= "port" value= "${redis_port}" />
<property
name= "hostName" value= "${redis_url}" />
</bean>
|
官方示例都是零配置的寫法,畫風變的太大以至於在AbstractHttpSessionApplicationInitializer這裡浪費了 很久。其實用上面這種方式,是完全不需要再寫AbstractHttpSessionApplicationInitializer的,他們乾的是一件 事。
關於子域的坑
發現spring session在獲取sessionid時,在CookieHttpSessionStrategy中並沒有做跨子域的處理...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private Cookie
createSessionCookie(HttpServletRequest request,
Map<String,
String> sessionIds) {
Cookie
sessionCookie = new Cookie(cookieName, "" );
if (isServlet3Plus)
{
sessionCookie.setHttpOnly( true );
}
sessionCookie.setSecure(request.isSecure());
sessionCookie.setPath(cookiePath(request));
//
TODO set domain?
...
private static String
cookiePath(HttpServletRequest request) {
return request.getContextPath()
+ "/" ;
}
|
其實這裡只要把cookiePath的返回值設定為統一的根路徑就能讓session id從根域獲取了,這樣同根下的所有web應用就可以輕鬆實現單點登入共享session了。既然找到了問題,解決就容易多了,下面列幾種解決方案:
- 改spring session原始碼,並重新打包
- 程式碼複用CookieHttpSessionStrategy,改cookiePath,並在spring注入時指定自己寫的這份Strategy
搭建spring session原始碼的開發環境太麻煩了,我用的方案2
1 2 3 |
private static String
cookiePath(HttpServletRequest request) {
return "/" ;
}
|
並在spring redis中加入如下配置
1 2 3 4 5 6 7 8 |
<bean
id= "redisRepository" class = "org.springframework.session.data.redis.RedisOperationsSessionRepository" >
<constructor-arg
ref= "jedisConnectionFactory" />
</bean>
<bean
id= "cookieHttpSessionStrategy" class
|