由于業務需要,昨天稍微研究了一下tomcat處理session的機制,對此有了更為深刻的理解,現在記下來,供大家參考和討論。
大家也許都了解,tomcat為了維持和瀏覽器之間的session對應關系,主要采用三種方式:
1.cookie紀錄sessionId;
2.url重寫;
3.隱藏表單,這個幾乎和url重寫意義相同;
之前,我一直非常相信瀏覽器的cookie,即便瀏覽器端關閉了cookie,也相信tomcat會自動幫忙重寫url,但是進入到wap這行后,cookie就不敢那么恭維了;
有些手機瀏覽器就只能保持一個cookie,并且對于cookie的維護性極差到一定地步,例如在“/”根目錄下的sessionId存儲與路徑為“/”的cookie中,而遇到“/a/”的情況,由于手機瀏覽器只能保持一個cookie,它居然愚蠢到將這個cookie里的sesionid等同于“/”中的sessionid,就不再紀錄了,也就是說“/a/”中的sessionid強制和“/”中的一樣,并且每次訪問“/a/”中的sessionid和“/”的一樣;
大家都知道,對于很多時候“/”和“/a/”的目標路徑,幾乎不在同一個服務,甚至不在同一臺服務器上,這點令我很是郁悶。
為了這個,我為每個鏈接的后面就加上了sessionid,這樣居然還是不行,后來我查看了許多tomcat相關的文檔,在配置文件的context中有個cookies選項,如果配置為false,則不信任瀏覽器的cookie,只信任url后面的jsessionid,但是公司的服務很大很雜,如果我更改了這個選項,怕影響到其它服務,最妥協的辦法就是讓tomcat先選擇url后面的sessionid,如果沒有再去cookie中去找,但是我沒有發現這樣的配置選項;
于是乎我查看起了tomcat的源代碼,后來發現CoyoteAdapter類中對于sessionid的處理是這樣的,顯示運行parseSessionId(req, request),這個方法是在url中獲取sessionid作為requestedSessionId,在同一方法的最后運行parseSessionCookiesId(req, request),這個方法負責在cookie中獲取sessionid,這個方法之前會判斷,如果配置中禁止cookie,則不取cookie中的了,也就是說無法優先選擇url中的sessionid,只能選擇或不選擇cookie的:(
這樣對于復寫tomcat代碼的夢想也幾乎覆滅了,于是只能執行強加手段了。
由于cookie中的sessionid是通過協議的head頭傳給服務器的,于是在apache中,強制改寫head頭,使“/”目錄下的sessionid在訪問"/a/"的時候強制實效,才解決了這個問題。
縱觀事件,難道我們就只能采取妥協的或者強制的方法才能解決一些郁悶的問題嗎?呵呵(苦笑ing)
不知道大家有沒有好的辦法解決cookie和session的問題,有多少辛酸,大家都說說吧。