goweb- session和數據存儲

session和數據存儲

Web開發中一個很重要的議題就是如何作好用戶的整個瀏覽過程的控制,由於HTTP協議是無狀態的,因此用戶的每一次請求都是無狀態的,咱們不知道在整個Web操做過程當中哪些鏈接與該用戶有關,咱們應該如何來解決這個問題呢?Web裏面經典的解決方案是cookie和session,cookie機制是一種客戶端機制,把用戶數據保存在客戶端,而session機制是一種服務器端的機制,服務器使用一種相似於散列表的結構來保存信息,每個網站訪客都會被分配給一個惟一的標誌符,即sessionID,它的存放形式無非兩種:要麼通過url傳遞,要麼保存在客戶端的cookies裏.固然,你也能夠將Session保存到數據庫裏,這樣會更安全,但效率方面會有所降低。javascript

session和cookie

session和cookie是網站瀏覽中較爲常見的兩個概念,也是比較難以辨析的兩個概念,但它們在瀏覽須要認證的服務頁面以及頁面統計中卻至關關鍵。咱們先來了解一下session和cookie怎麼來的?考慮這樣一個問題:java

如何抓取一個訪問受限的網頁?如新浪微博好友的主頁,我的微博頁面等。git

顯然,經過瀏覽器,咱們能夠手動輸入用戶名和密碼來訪問頁面,而所謂的「抓取」,其實就是使用程序來模擬完成一樣的工做,所以咱們須要瞭解「登陸」過程當中到底發生了什麼。github

當用戶來到微博登陸頁面,輸入用戶名和密碼以後點擊「登陸」後瀏覽器將認證信息POST給遠端的服務器,服務器執行驗證邏輯,若是驗證經過,則瀏覽器會跳轉到登陸用戶的微博首頁,在登陸成功後,服務器如何驗證咱們對其餘受限制頁面的訪問呢?由於HTTP協議是無狀態的,因此很顯然服務器不可能知道咱們已經在上一次的HTTP請求中經過了驗證。固然,最簡單的解決方案就是全部的請求裏面都帶上用戶名和密碼,這樣雖然可行,但大大加劇了服務器的負擔(對於每一個request都須要到數據庫驗證),也大大下降了用戶體驗(每一個頁面都須要從新輸入用戶名密碼,每一個頁面都帶有登陸表單)。既然直接在請求中帶上用戶名與密碼不可行,那麼就只有在服務器或客戶端保存一些相似的能夠表明身份的信息了,因此就有了cookie與session。golang

cookie,簡而言之就是在本地計算機保存一些用戶操做的歷史信息(固然包括登陸信息),並在用戶再次訪問該站點時瀏覽器經過HTTP協議將本地cookie內容發送給服務器,從而完成驗證,或繼續上一步操做。web

session,簡而言之就是在服務器上保存用戶操做的歷史信息。服務器使用session id來標識session,session id由服務器負責產生,保證隨機性與惟一性,至關於一個隨機密鑰,避免在握手或傳輸中暴露用戶真實密碼。但該方式下,仍然須要將發送請求的客戶端與session進行對應,因此能夠藉助cookie機制來獲取客戶端的標識(即session id),也能夠經過GET方式將id提交給服務器。數據庫

cookie是有時間限制的,根據生命期不一樣分紅兩種:會話cookie和持久cookie;後端

若是不設置過時時間,則表示這個cookie的生命週期爲從建立到瀏覽器關閉爲止,只要關閉瀏覽器窗口,cookie就消失了。這種生命期爲瀏覽會話期的cookie被稱爲會話cookie。會話cookie通常不保存在硬盤上而是保存在內存裏。瀏覽器

若是設置了過時時間(setMaxAge(606024)),瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie依然有效直到超過設定的過時時間。存儲在硬盤上的cookie能夠在不一樣的瀏覽器進程間共享,好比兩個IE窗口。而對於保存在內存的cookie,不一樣的瀏覽器有不一樣的處理方式。   安全

session

session,中文常常翻譯爲會話,其原本的含義是指善始善終的一系列動做/消息,好比打電話是從拿起電話撥號到掛斷電話這中間的一系列過程能夠稱之爲一個session。然而當session一詞與網絡協議相關聯時,它又每每隱含了「面向鏈接」和/或「保持狀態」這樣兩個含義。

session在Web開發環境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器端之間保持狀態的解決方案。有時候Session也用來指這種解決方案的存儲結構。

session機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息。

但程序須要爲某個客戶端的請求建立一個session的時候,服務器首先檢查這個客戶端的請求裏是否包含了一個session標識-稱爲session id,若是已經包含一個session id則說明之前已經爲此客戶建立過session,服務器就按照session id把這個session檢索出來使用(若是檢索不到,可能會新建一個,這種狀況可能出如今服務端已經刪除了該用戶對應的session對象,但用戶人爲地在請求的URL後面附加上一個JSESSION的參數)。若是客戶請求不包含session id,則爲此客戶建立一個session而且同時生成一個與此session相關聯的session id,這個session id將在本次響應中返回給客戶端保存。

session機制自己並不複雜,然而其實現和配置上的靈活性卻使得具體狀況複雜多變。這也要求咱們不能把僅僅某一次的經驗或者某一個瀏覽器,服務器的經驗看成廣泛適用的。

session和cookie的目的相同,都是爲了克服http協議無狀態的缺陷,但完成的方法不一樣。session經過cookie,在客戶端保存session id,而將用戶的其餘會話消息保存在服務端的session對象中,與此相對的,cookie須要將全部信息都保存在客戶端。所以cookie存在着必定的安全隱患,例如本地cookie中保存的用戶名密碼被破譯,或cookie被其餘網站收集(例如:1. appA主動設置域B cookie,讓域B cookie獲取;2. XSS,在appA上經過javascript獲取document.cookie,並傳遞給本身的appB)。

Go如何使用session

經過上一小節的介紹,咱們知道session是在服務器端實現的一種用戶和服務器之間認證的解決方案,目前Go標準包沒有爲session提供任何支持,

ession建立過程

ssession的基本原理是由服務器爲每一個會話維護一份信息數據,客戶端和服務端依靠一個全局惟一的標識來訪問這份數據,以達到交互的目的。當用戶訪問Web應用時,服務端程序會隨須要建立session,這個過程能夠歸納爲三個步驟:

  • 生成全局惟一標識符(sessionid);
  • 開闢數據存儲空間。通常會在內存中建立相應的數據結構,但這種狀況下,系統一旦掉電,全部的會話數據就會丟失,若是是電子商務類網站,這將形成嚴重的後果。因此爲了解決這類問題,你能夠將會話數據寫到文件裏或存儲在數據庫中,固然這樣會增長I/O開銷,可是它能夠實現某種程度的session持久化,也更有利於session的共享;
  • 將session的全局惟一標示符發送給客戶端。

以上三個步驟中,最關鍵的是如何發送這個session的惟一標識這一步上。考慮到HTTP協議的定義,數據無非能夠放到請求行、頭域或Body裏,因此通常來講會有兩種經常使用的方式:cookie和URL重寫。

  • Cookie 服務端經過設置Set-cookie頭就能夠將session的標識符傳送到客戶端,而客戶端此後的每一次請求都會帶上這個標識符,另一般包含session信息的cookie會將失效時間設置爲0(會話cookie),即瀏覽器進程有效時間。至於瀏覽器怎麼處理這個0,每一個瀏覽器都有本身的方案,但差異都不會太大(通常體如今新建瀏覽器窗口的時候);

  • URL重寫 所謂URL重寫,就是在返回給用戶的頁面裏的全部的URL後面追加session標識符,這樣用戶在收到響應以後,不管點擊響應頁面裏的哪一個連接或提交表單,都會自動帶上session標識符,從而就實現了會話的保持。雖然這種作法比較麻煩,可是,若是客戶端禁用了cookie的話,此種方案將會是首選。

預防session劫持

session劫持是一種普遍存在的比較嚴重的安全威脅,在session技術中,客戶端和服務端經過session的標識符來維護會話, 但這個標識符很容易就能被嗅探到,從而被其餘人利用。它是中間人攻擊的一種類型

session劫持防範

cookieonly和token
經過上面session劫持的簡單演示能夠了解到session一旦被其餘人劫持,就很是危險,劫持者能夠僞裝成被劫持者進行不少非法操做。那麼如何有效的防止session劫持呢?

其中一個解決方案就是sessionID的值只容許cookie設置,而不是經過URL重置方式設置,同時設置cookie的httponly爲true,這個屬性是設置是否可經過客戶端腳本訪問這個設置的cookie,第一這個能夠防止這個cookie被XSS讀取從而引發session劫持,第二cookie設置不會像URL重置方式那麼容易獲取sessionID。

第二步就是在每一個請求裏面加上token,實現相似前面章節裏面講的防止form重複遞交相似的功能,咱們在每一個請求裏面加上一個隱藏的token,而後每次驗證這個token,從而保證用戶的請求都是惟一性。

間隔生成新的SID

還有一個解決方案就是,咱們給session額外設置一個建立時間的值,一旦過了必定的時間,咱們銷燬這個sessionID,從新生成新的session,這樣能夠必定程度上防止session劫持的問題。

這章咱們學習了什麼是session,什麼是cookie,以及他們二者之間的關係。可是目前Go官方標準包裏面不支持session,因此咱們設計了一個session管理器,實現了session從建立到銷燬的整個過程。而後定義了Provider的接口,使得能夠支持各類後端的session存儲,而後咱們在第三小節裏面介紹瞭如何使用內存存儲來實現session的管理。第四小節咱們講解了session劫持的過程,以及咱們如何有效的來防止session劫持。經過這一章的講解,但願可以讓讀者瞭解整個sesison的執行原理以及如何實現,並且是如何更加安全的使用session。

慚愧慚愧,並無徹底吸取

連接

相關文章
相關標籤/搜索