1. 程式人生 > >跨域、跨伺服器呼叫時候session丟失的問題總結!!!

跨域、跨伺服器呼叫時候session丟失的問題總結!!!

http://blog.csdn.net/zq9017197/article/details/6326667

這篇文件是最近一次工作中遇到問題的總結,且聽我娓娓道來:(可能有很多地方不對,我只是這樣想通拉。)

最近新進一個公司,做的專案是手機支付系統。由於涉及到金錢相關的,所以安全性要求特別的高。專案分了很多個子系統,在部署(測試)的時候是每個Tomcat上面只放一個子系統。比如現在有5個子系統,那麼就會對應5個Tomcat啟動了放在linux上面的。為什麼這麼做?試想如果在上線以後,如果其中一個系統有問題要重啟伺服器,5個子系統都放在一起的話,那不是全部都會跟著重啟了!現在說說我們遇到的問題了。

使用者登入後,在管理子系統,有一個充值連線,會跳到充值子系統去充值。這樣跨JVM的跳轉只能用redirect來跳,但是使用者自己的登入狀態就會丟失了(登入session丟失)。後來改為forward跳轉到自己的jsp頁面,然後在form提交到充值子系統去充值。在本地開發測試的時候session是不會丟失的,但是釋出到linux下面的Tomcat就會丟失。找了各種原因都以為是作業系統差異的問題。

後來發現一個這樣的區別,開發測試是兩個IP不同的埠號的跳轉,釋出到linux上面測試是同一個IP不同的埠號的跳轉。這樣涉及到對瀏覽器session和cookies的瞭解程度拉。

首先session是存放在容器裡面的,而且一次會話的session會生成一個jsessionid,在管理session的時候是根據jsessionid去尋找,能找到就不會建立新的session,找不到才建立新的session,確定這才是一次新的會話。而cookies是存放在客戶端的檔案。jsessionid也會放到cookies裡面。

兩個IP、兩個埠就會有兩個session、兩個cookies這樣session是會丟失的。首先在管理子系統第一次登入會生成一個jsessionid,在一個cookies裡面去是找不到這個session的。就會建立登入成功的session。然後跳轉到充值子系統,也會在充值子系統生成一個jsessionid,到另一個cookies裡面去找這個session也是找不到的,也會建立一個session。以前的session就這樣丟失拉。

一個IP、兩個埠就會有兩個session、一個cookies這樣session也是會丟失的。首先在管理子系統第一次登入會生成一個jsessionid,在cookies裡面去是找不到這個session的。就會建立登入成功的session。然後跳轉到充值子系統,也會在充值子系統生成一個jsessionid,到同樣這個cookies裡面去找這個session也是找不到的,也會建立一個session覆蓋以前的session。

解決把法就是不讓jsessionid自動生成,放到cookies裡面。而是在url裡面傳遞jsessionid,不用靠cookies。說通俗點這個就叫url重寫。

這樣在管理系統第一次登入會生成一個jsessionid,建立登入session。當到充值系統的時候我會把jsessionid傳過去那邊也會生成一個session。意思就是兩個容器各自生成了各自的session,但是共用的同一個jsessionid。這樣每次到容器裡面去取session內容都是根據同一個jsessionid去取,如果建立過的話。裡面肯定是能拿到的。但是裡面的內容各自建立的又不一樣。這樣session就不會丟失老!!!

要讓url重寫有很多方法,比如:

<c:url value=""/>

response.encodeRedirectUrl("");
response.encodeUrl("");

等多種方法。但要讓cookies裡面的jsessionid不被使用就需要瀏覽器完全禁用cookies等。還有個簡單的方法就是在Tomcat裡面配置:

tomcat_home/conf/context.xml裡面把<Context>改為<Context cookies = "false">這樣就好拉!!!

然後url就會自動變成這個樣子:

所以每個請求要加上jsessionid引數,後臺程式碼通過jsessionid,獲取session,再獲取使用者資訊