由於http協議無狀態,兩次請求服務器沒法分辨是否爲同一帳號請求。登陸就是用某種方法讓服務器識別不一樣的請求都是誰發出的。javascript
從登陸到登出的過程當中,服務器維護了一個能夠識別用戶信息的數據結構,廣義上來講,這個過程叫session,就是保持了一個會話php
區別於狹義的session,狹義session指的是登陸成功後服務端存儲的用戶信息
過程:html
將sessionId存在cookie並非一種強制的方案,而是你們通常都這麼作,並且發請求的時候符合domain和path的時候,會自動帶上cookie,省去了手動塞的過程。
二者區別:前端
以jwt(json web token)爲例:java
主要由三部分組成git
header 頭部 描述簽名算法和token的類型,類型通常都是JWT { "alg": "HS256", "typ": "JWT" } payload 負載 用戶信息 { "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1555341649998 } signature 簽名 對前兩部分的簽名,實現須要一個密鑰(secret)這個secret只有服務器才知道,而後使用header裏面的算法按照以下方法來簽名: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
最後的 jwt = base64url(header) + "." + base64url(payload) + "." + signaturegithub
jwt能夠放在response中返回,也能夠放在cookie中返回。客戶端發起請求時,官方推薦放在HTTP header中:golang
Authorization: Bearer <token>
單點登陸(Single Sign On),簡稱爲 SSO.web
定義是在多個應用系統中,用戶只須要登陸一次就能夠訪問全部相互信任的應用系統。算法
一個企業通常狀況下只有一個域名,經過二級域名區分不一樣的系統。好比咱們有個域名叫作:a.com,同時有兩個業務系統分別爲:app1.a.com和app2.a.com。咱們要作單點登陸(SSO),須要一個登陸系統,叫作:sso.a.com。
問題一:在sso.a.com登錄後,由於cookie不能跨域,因此沒法在app1.a.com和app2.a.com這兩個域名發送請求時攜帶cookie
解決方法:sso登陸之後,能夠將Cookie的域設置爲頂域,即.a.com,這樣全部子域的系統均可以訪問到頂域的Cookie。
問題二:sso、app1和app2是不一樣的應用,它們的session存在本身的應用內,是不共享的
解決辦法:把3個系統的Session共享。共享Session的解決方案有不少,例如:Spring-Session。
說到單點登陸,就確定會見到這個名詞:CAS (Central Authentication Service)
上圖是CAS官網上的標準流程,具體流程以下:
app1登錄後訪問app2的流程
業務系統拿ST再次訪問SSO進行驗證,這個步驟是爲了保證安全。若是業務系統不確認一下這個用戶收否是僞造的,那直接在瀏覽器中敲入回調地址帶上用戶信息便可登陸。
Cookie既指整個狀態保存機制,也指用戶保存狀態的數據自己,由String類型的name和value以及若干屬性組成。
Cookie由服務端生成,保存在瀏覽器。經過兩個Http Header:Set-Cookie和Cookie進行傳輸。
不少瀏覽器會提供讀Cookie和寫Cookie的api給運行在其上Javascript腳本使用,一般的api是操做docment.cookie:
document.cookie=「SID=31d4d; domain=example.com; path=/;」;
其它屬性僅用做讀寫時的權限控制,不做爲cookie標識。
Domain
和 Path
標識定義了Cookie的做用域:即Cookie應該發送給哪些URL。
Domain
標識指定了哪些主機能夠接受Cookie。若是不指定,默認爲當前文檔的主機(不包含子域名)。若是指定了Domain
,則通常包含子域名。
例如,若是設置 Domain=mozilla.org
,則Cookie也包含在子域名中(如developer.mozilla.org
)。
Path
標識指定了主機下的哪些路徑能夠接受Cookie(該URL路徑必須存在於請求URL中)。以字符 %x2F
("/") 做爲路徑分隔符,子路徑也會被匹配。
例如,設置 Path=/docs
,則如下地址都會匹配:
/docs
/docs/Web/
/docs/Web/HTTP
domain向上通配,path向下通配
會話期Cookie:瀏覽器關閉以後會被自動刪除,僅在會話期內有效。不須要指定過時時間(Expires
)或者有效期(Max-Age)。
持久性Cookie:能夠指定一個特定的過時時間(Expires
)或有效期(Max-Age
)。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
提示:當Cookie的過時時間被設定時,設定的日期和時間只與客戶端相關,而不是服務端。
須要注意的是,有些瀏覽器提供了會話恢復功能,這種狀況下即便關閉了瀏覽器,會話期Cookie也會被保留下來,就好像瀏覽器歷來沒有關閉同樣。
Cookie的有效期過長可能致使通行證泄露。好比用戶使用了公用電腦,關閉瀏覽器時,沒有點擊註銷。這樣Cookie就留存在這臺電腦上,其它人只需打開瀏覽器便可獲取其在網站上的cookie。
通常保存通行證的cookie應該設置爲session有效的cookie,並在用戶選擇記住登陸狀態時,提醒用戶,不要再公用電腦上作這樣的勾選。
HTTP明文傳輸數據的特性,使得攻擊者可從網路上抓包獲取Cookie。
解決方案:
假如網站存在XSS漏洞,那麼惡意JS可直接讀取Cookie中的通行證。能夠經過指定Cookie的HttpOnly屬性。對於指定了HttpOnly的Cookie,瀏覽器會拒絕JS讀寫。
XSS仍有可能利用服務端漏洞獲取cookie: - 服務端有可能在請求的正常響應中包含通行證。不要笑,這真的有,尤爲如今不少公司app和web共用一套後臺; - 服務端可能有漏洞致使cookie包含在請求響應中,從而被竊取。好比:Apache CEV-2012-005
因此HttpOnly不是銀彈,XSS也有不少其它的危害。但至少,HttpOnly能夠避免通行證在瀏覽器被JS直接讀取。
好比在不安全聊天室或論壇上的一張圖片,它其實是一個給你銀行服務器發送提現的請求:
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
當你打開含有了這張圖片的HTML頁面時,若是你以前已經登陸了你的銀行賬號而且Cookie仍然有效(尚未其它驗證步驟),你銀行裏的錢極可能會被自動轉走。有一些方法能夠阻止此類事件的發生:
參考資料: