最近在做登入和權限控制子產品,用到了session,發現session的好多方法都不熟悉,而且以前也聽說過JsessionId 之類session竊取的事,對這些一直都是一知半解。今天索性google了很多資料,先上sun的官網去看session的文檔了解一些方法,又找了别人關于session的看法。
總結如下:
1,session是什麼? what
session經常譯為會話,以打電話為例,從開始撥号到挂斷電話就是你會話的生存周期。
2,session 做什麼用的 why?
首先舉個例子:
咖啡店舉行 消費滿5杯咖啡贈送一杯的活動,可每個人一次消費5杯的時候非常少。這時候有3種辦法:
1,店員看到每個顧客時都能記住其消費了多少杯,進而給其優惠,這是協定本身具有狀态
2,給每個顧客一個卡片,上面記錄顧客的每次消費,這是用戶端儲存狀态
3,給每個顧客一個卡片,卡片上隻有一個編号,顧客每次的消費記錄在店裡,這就是 服務端有狀态
而http本身是無狀态的,是以我們隻能使用2,3中方法,來儲存一些資訊。
實際采用的是第3種方法,伺服器段儲存一次會話所有的資訊,并生成一個唯一的id,這個id沒有規律而且不會重複,将這個id傳回到客戶段,儲存到cookie中。每次通路伺服器時,用戶端都會偷偷将這個id傳到伺服器,伺服器根據id查到這次會話儲存的内容。就能實作會話中共享一些資料。
3,session怎樣建立和銷毀 ? how
session是儲存在記憶體中的,是以會有一些性能上的影響。是以本着這個原則,session是隻有在使用到的時候才會被建立,如果始終沒有用到session,這個session是永遠不會被建立的。
比如: 通路servlet ,隻要你代碼中沒有 request.getSession()或request.getSession(true);這兩行是等價的,那session是不會建立。又 當你通路靜态頁面時,根本不會生成servlet,是以也不會建立session。
下面解釋一些疑惑: session是第一次請求時建立的?
大家都知道 jsp是被編譯成servlet才執行的,問題就在jsp編譯的過程。
jsp中有個<%@ page session="true/false"%> 這個開關表示是否建立session,當你不寫這行時,它會預設給你加上這句。是以會造成上面的疑惑。當然還有一些标簽中可能有getSession()操作,會産生一些不必要的session。
session隻能在服務端銷毀,有三種途徑: 1,到達session的最大請求間隔時間時,2,session。invalidate()
3,伺服器程序當掉。
這裡也有一些疑惑: 浏覽器關閉時,session就會登出。
首先浏覽器關閉時,浏覽器并沒有給伺服器發送任何消息,是以伺服器不會知道浏覽器何時關閉了。
上面我們知道取得session 是因為浏覽器cookie中有sessionid,而普通cookie通常會是會話cookie,也就是說浏覽器關閉時,這個cookie會被登出,是以當你再通路伺服器時就沒有sessionid了,是以造成session關閉了的假象,如果昵稱通過特殊方法将sessionid傳遞給伺服器,你會發現session還在。
如果想讓cookie儲存時間長一些,就需要手動指定cookie的過期時間
4,實際項目中的難點:
1,浏覽器禁用cookie
這就沒辦法儲存sessionid了,可以采用url重寫,轉發,加隐藏字段等方法來将sessionid傳給伺服器。
如: baidu.com:jsessionid=adfasdfasdfasdfasdfafdadf?asdfasdf
baidu.com?jsessionid=asdfasdfasdfadsfad&&adfdf
這根據伺服器的不同實作,第一種可以将普通參數區分開。
2,多人共用session的問題
例: a 通路 baidu.com ,但他沒有帳号,于是他将連接配接 baidu.com/login.jsp?jsessionid=adsfasdfad(這個a的sessionid) 發給B, B登入後,a就相當于用b的帳号登入了。你們可以在在本地試試。
解決方法: 當發現通過sessionid從url指定時, 建立一個新的session,将舊session的資訊複制到 新sessoin中,然後将新session登出。就能防止上面那種情況了。
3,一個帳号多地方登入
比如: 你用abc帳号登入了baidu.com,有打開了一個浏覽器,又用abc帳号登入了一次。當不設計敏感操作時,這無所謂,而當你做一些敏感操作時就必須禁止這樣情況,防止同時操作,造成重複操作,或者資料損壞。
解決方法: 監聽session,将username和sessionid對應起來,當username再次登入時,登出掉以前的session,儲存現在的session,這也是一種比較不錯的方案。
這是 sghcel 畫的圖,挺不錯的: