1. 程式人生 > >session衝突問題產生的原因和解決方法:

session衝突問題產生的原因和解決方法:


背景知識
    1. cookie與session的關係
       cookie和session的方案雖然分別屬於客戶端和服務端,但是服務端的session的實現對客戶端的cookie有依賴關係的,上面我講到服務端執行session機制時候會生成session的id值,
       這個id值會發送給客戶端,客戶端每次請求都會把這個id值放到http請求的頭部發送給服務端,而這個id值在客戶端會儲存下來,儲存的容器就是cookie,
       因此當我們完全禁掉瀏覽器的cookie的時候,服務端的session也會不能正常使用(注意:有些資料說ASP解決這個問題,當瀏覽器的cookie被禁掉,
       服務端的session任然可以正常使用,ASP我沒試驗過,但是對於網路上很多用php和jsp編寫的網站,我發現禁掉cookie,網站的session都無法正常的訪問)


問題現象

    專案A和專案B,部署在同一臺伺服器下,使用相同的域名,他們的訪問方式類似於下面這樣:
    http://test.domain.com/A/index.jsp
    http://test.domain.com/B/index.jsp


    A專案中有個連結到B專案的連結(使用者名稱和密碼放在引數裡,到B專案中的方法中驗證,組裝user並設定到session裡),
    當在A專案中點選了連結後會將B的頁面內嵌在A系統中,再次點選A專案的其他選單時退出到登入頁面


問題原因
    經過檢查,發現點選過B連結後,原來儲存在session中的user對應沒有了,再次點選A的其他選單時因為找不到登入資訊而被退回到登入頁面。


    websphere 伺服器預設產生sessionid為'JSESSIONID',當登入A系統時,伺服器為A系統生成了SESSIONID=123的session資訊儲存到伺服器,並把
    sessionId及其值儲存到客戶端cookie中,每次發起同域名的請求時就會把這個sessionid和值傳遞到伺服器。
    當點選B連結時,由於B專案和A專案同域名,所以會傳遞SESSIONID=123到B專案容器,B專案所在容器發現SESSIONID=123並不存在,就新建了個SESSIONID=456
    並傳遞給客戶端瀏覽器存入test.domain.com域名對應的cookie,此時原來在A專案產生的SESSIONID=123已經被覆蓋成SESSIONID=456,所以當再次點選
    A專案的其他連結時會傳遞SESSIONID=456給A專案伺服器,此時A專案伺服器又變得不認識了,所以有新建了個session,回傳給客戶端儲存在同名的COOKIE中,導致新的session裡沒有user物件資訊
    而被退回到登入頁面。


解決方法

    改變A或B所在web容器的session的ID名稱(也即儲存在客戶端的cookie名稱),如把B專案所在容器的session的ID名稱改為SESSIONIDA (結尾多加個A)
    這樣,兩個專案即使有相互交叉session也不會衝突覆蓋了,請求A專案和B專案都發送SESSIONID=123和SESSIONIDA=456兩個cookie,各自用各自的sessionID名稱取值  
    (經測試,當同域名不同sessionId時,第二次請求B時會為B單獨生成cookie檔案,從而區別於A生成的檔案,當兩個sessionId一致時始終是一個cookie檔案,從而導致衝突
    當請求A專案是,伺服器設定SESSIONID=123到客戶端,當請求B專案時,伺服器設定SESSIONID=456到客戶端,分開儲存,但是因為還是在同一域名下,所以此後請求A專案和B專案
    會把兩個cookie都發送到伺服器端,伺服器端根據自己容器定義的SESSIONID名稱取對應的cookie值,從而避免衝突)




    其他方法:也可通過改變cookie儲存路徑來實現。