web登陸方式/單點登陸SSO/Cookie詳解與安全問題

web登陸方式

爲何會有登錄態

由於http協議無狀態,兩次請求服務器沒法分辨是否爲同一帳號請求。登陸就是用某種方法讓服務器識別不一樣的請求都是誰發出的。javascript

從登陸到登出的過程當中,服務器維護了一個能夠識別用戶信息的數據結構,廣義上來講,這個過程叫session,就是保持了一個會話php

區別於狹義的session,狹義session指的是登陸成功後服務端存儲的用戶信息

服務端session和客戶端sessionId 存儲於cookie的方式

img

過程:html

  1. 客戶端帶着用戶名和密碼去訪問 /login 接口,服務器端收到後校驗正確就會在服務器端存儲一個sessionId和session的映射關係
  2. 服務器端返回response,而且將sessionId以set-cookie的方式種在客戶端
  3. 客戶端發起非登陸請求時,服務端經過cookie中的sessionId找到對應的session來知道這次請求是誰發出的。
將sessionId存在cookie並非一種強制的方案,而是你們通常都這麼作,並且發請求的時候符合domain和path的時候,會自動帶上cookie,省去了手動塞的過程。

token / jwt 方式

二者區別:前端

  • sessionId的方式本質是把用戶狀態信息維護在server端,cookie傳輸。雖然方便但有安全問題。
  • token的方式把用戶信息生成一串token傳給前端,前端每次發請求時帶上token,傳回給服務器端;服務器端收到請求以後,解析token而且驗證相關信息;
  • 最本質的區別是經過解析token的計算時間換取了session的存儲空間

以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>

存在的問題

  • session須要存儲,多機存儲和用戶量增多時,對存儲空間有要求
  • session+cookie裏面存sessionId的方式可能會有csrf攻擊的問題,常見的方式是使用csrf_token來解決
  • jwt的過時時間須要結合業務作設置,並且jwt一旦派發出去,後端沒法強行使其做廢

跨頁面登錄態同步方法

單點登陸(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_flow_diagram

上圖是CAS官網上的標準流程,具體流程以下:

  1. 用戶訪問app系統,app系統是須要登陸的,但用戶如今沒有登陸。
  2. 跳轉到CAS server,即SSO登陸系統,之後圖中的CAS Server咱們統一叫作SSO系統。 SSO系統也沒有登陸,彈出用戶登陸頁。
  3. 用戶填寫用戶名、密碼,SSO系統進行認證後,將登陸狀態寫入SSO的session,瀏覽器(Browser)中寫入SSO域下的Cookie。
  4. SSO系統登陸完成後會生成一個ST(Service Ticket),而後跳轉到app系統,同時將ST做爲參數傳遞給app系統。
  5. app系統拿到ST後,從後臺向SSO發送請求,驗證ST是否有效。
  6. 驗證經過後,app系統將登陸狀態寫入session並設置app域下的Cookie。

app1登錄後訪問app2的流程

  1. 用戶訪問app2系統,app2系統沒有登陸,跳轉到SSO。
  2. 因爲SSO已經登陸了,不須要從新登陸認證。
  3. SSO生成ST,瀏覽器跳轉到app2系統,並將ST做爲參數傳遞給app2。
  4. app2拿到ST,後臺訪問SSO,驗證ST是否有效。
  5. 驗證成功後,app2將登陸狀態寫入session,並在app2域下寫入Cookie。

業務系統拿ST再次訪問SSO進行驗證,這個步驟是爲了保證安全。若是業務系統不確認一下這個用戶收否是僞造的,那直接在瀏覽器中敲入回調地址帶上用戶信息便可登陸。

cookie相關知識點及安全性問題

是什麼,存在哪兒,怎麼傳輸

Cookie既指整個狀態保存機制,也指用戶保存狀態的數據自己,由String類型的name和value以及若干屬性組成。

Cookie由服務端生成,保存在瀏覽器。經過兩個Http Header:Set-Cookie和Cookie進行傳輸。

HttpCookie

不少瀏覽器會提供讀Cookie和寫Cookie的api給運行在其上Javascript腳本使用,一般的api是操做docment.cookie:

document.cookie=「SID=31d4d; domain=example.com; path=/;」;

關鍵屬性和不一樣類型的cookie

Domain、Path、Name三者惟一肯定一個cookie。

其它屬性僅用做讀寫時的權限控制,不做爲cookie標識。

DomainPath 標識定義了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分爲會話期cookie和持久性cookie

會話期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流量

HTTP明文傳輸數據的特性,使得攻擊者可從網路上抓包獲取Cookie。

解決方案:

  • 服務端使用HTTPS
  • 指定cookie的secure屬性,該屬性使cookie只能在HTTPS請求中帶出。

利用XSS漏洞讀取保存在cookie的通行證

假如網站存在XSS漏洞,那麼惡意JS可直接讀取Cookie中的通行證。能夠經過指定Cookie的HttpOnly屬性。對於指定了HttpOnly的Cookie,瀏覽器會拒絕JS讀寫

XSS仍有可能利用服務端漏洞獲取cookie: - 服務端有可能在請求的正常響應中包含通行證。不要笑,這真的有,尤爲如今不少公司app和web共用一套後臺; - 服務端可能有漏洞致使cookie包含在請求響應中,從而被竊取。好比:Apache CEV-2012-005

因此HttpOnly不是銀彈,XSS也有不少其它的危害。但至少,HttpOnly能夠避免通行證在瀏覽器被JS直接讀取

跨站請求僞造(CSRF)

好比在不安全聊天室或論壇上的一張圖片,它其實是一個給你銀行服務器發送提現的請求:

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">

當你打開含有了這張圖片的HTML頁面時,若是你以前已經登陸了你的銀行賬號而且Cookie仍然有效(尚未其它驗證步驟),你銀行裏的錢極可能會被自動轉走。有一些方法能夠阻止此類事件的發生:

  • 設置Cookie的SameSite屬性。該屬性規定cookie只會在當前正在訪問(瀏覽器地址欄)的域名與cookie的domain可匹配時,纔會帶出。
  • 任何敏感操做都須要確認;
  • 用於敏感信息的Cookie只能擁有較短的生命週期;
  • 更多方法能夠查看OWASP CSRF prevention cheat sheet_Prevention_Cheat_Sheet)。

參考資料:

前端應該知道的web登陸

session和cookie

單點登陸(SSO)看這一篇就夠了

Cookie與Passport安全

HTTP cookies

相關文章
相關標籤/搜索