登陸認證幾乎是任何一個系統的標配,web 系統、APP、PC 客戶端等,好多都須要註冊、登陸、受權認證。
場景說明
以一個電商系統,假設淘寶爲例,若是咱們想要下單,首先須要註冊一個帳號。擁有了帳號以後,咱們須要輸入用戶名(好比手機號或郵箱)、密碼完成登陸過程。以後若是你在一段時間內再次進入系統,是不須要輸入用戶名和密碼的,只有在連續長時間不登陸的狀況下(例如一個月沒登陸過)訪問系統,再次須要輸入用戶名和密碼。若是使用頻率很頻繁,一般是一年都不用再輸一次密碼,因此常常在換了一臺電腦或者一部手機以後,一些常用的網站或 APP 不記得密碼了。html
提煉出來整個過程大概就是以下幾步:git
- 首次使用,須要經過郵箱或手機號註冊;
- 註冊完成後,須要提供用戶名和密碼完成登陸;
- 下次再使用,一般不會再次輸入用戶名和密碼便可直接進入系統並使用其功能(除非連續長時間未使用);
經常使用的認證方式
OAuth 認證
OAuth 認證比較常見的就是微信登陸、微博登陸、qq登陸等,簡單來講就是利用這些比較權威的網站或應用開放的 API 來實現用戶登陸,用戶能夠不用在你的網站或應用上註冊帳號,直接用已有的微信、微博、qq 等帳號登陸。github
這同樣一來,即省了用戶註冊的時間,又簡化了你的系統的帳號體系。從而既能夠提升用戶註冊率能夠節省開發時間,同時,安全性也有了保障。web
維基百科對它的解釋摘要以下:算法
OAuth容許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每個令牌受權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth讓用戶能夠受權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非全部內容。
假設咱們開發了一個電商平臺,並集成了微信登陸,以這個場景爲例,說一下 OAuth 的工做原理。數據庫
講以前須要瞭解其中涉及到的幾個角色:json
- 用戶:即便用咱們平臺的用戶
- 用戶終端:即最終用戶使用的 APP 端或 web 端
- 應用服務器端:即咱們的服務器端
- 受權服務器端:這裏就是微信處理受權請求的服務器
好的,接下來開始在咱們的電商平臺web端實現微信登陸功能。微信網頁受權是受權碼模式(authorization code)的 OAuth 受權模式。跨域
- 咱們電商平臺的用戶過來登陸,經常使用場景是點擊「微信登陸」按鈕;
- 接下來,用戶終端將用戶引導到微信受權頁面;
- 用戶贊成受權,應用服務器重定向到以前設置好的 redirect_uri (應用服務器所在的地址),並附帶上受權碼(code);
- 應用服務器用上一步獲取的 code 向微信受權服務器發送請求,獲取 access_token,也就是上面說的令牌;
- 以後應用服務器用上一步獲取的 access_token 去請求微信受權服務器獲取用戶的基本信息,例如頭像、暱稱等;
Cookie-Session 認證
早期互聯網以 web 爲主,客戶端是瀏覽器,因此 Cookie-Session 方式最那時候最經常使用的方式,直到如今,一些 web 網站依然用這種方式作認證。瀏覽器
認證過程大體以下:安全
- 用戶輸入用戶名、密碼或者用短信驗證碼方式登陸系統;
- 服務端驗證後,建立一個 Session 信息,而且將 SessionID 存到 cookie,發送回瀏覽器;
- 下次客戶端再發起請求,自動帶上 cookie 信息,服務端經過 cookie 獲取 Session 信息進行校驗;
弊端
- 只能在 web 場景下使用,若是是 APP 中,不能使用 cookie 的狀況下就不能用了;
- 即便能在 web 場景下使用,也要考慮跨域問題,由於 cookie 不能跨域;
- cookie 存在 CSRF(跨站請求僞造)的風險;
- 若是是分佈式服務,須要考慮 Session 同步問題;
Cookie-Session 改造版
因爲傳統的 Cookie-Session 認證存在諸多問題,能夠把上面的方案改造一下。改動的地方以下:
- 不用 cookie 作客戶端存儲,改用其餘方式,web 下使用 local storage,APP 中使用客戶端數據庫,這樣就實現了跨域,而且避免了 CSRF ;
- 服務端也不存 Session 了,把 Session 信息拿出來存到 Redis 等內存數據庫中,這樣即提升了速度,又避免了 Session 同步問題;
通過改造以後變成了以下的認證過程:
- 用戶輸入用戶名、密碼或者用短信驗證碼方式登陸系統;
- 服務端通過驗證,將認證信息構造好的數據結構存儲到 Redis 中,並將 key 值返回給客戶端;
- 客戶端拿到返回的 key,存儲到 local storage 或本地數據庫;
- 下次客戶端再次請求,把 key 值附加到 header 或者 請求體中;
- 服務端根據獲取的 key,到 Redis 中獲取認證信息;
基於JWT的Token認證
上面的方案雖然通過了改版,但仍是須要客戶端和服務器端維持一個狀態信息,好比用 cookie 換 session ,或者用 key 換 Redis 的 value 信息,基於 JWT 的 Token 認證方案能夠省去這個過程。
JSON Web Token(JWT)是一個很是輕巧的規範。這個規範容許咱們使用JWT在用戶和服務器之間傳遞安全可靠的信息。
認證過程
- 依然是用戶登陸系統;
- 服務端驗證,將認證信息經過指定的算法(例如HS256)進行加密,例如對用戶名和用戶所屬角色進行加密,加密私鑰是保存在服務器端的,將加密後的結果發送給客戶端,加密的字符串格式爲三個"." 分隔的字符串 Token,分別對應頭部、載荷與簽名,頭部和載荷均可以經過 base64 解碼出來,簽名部分不能夠;
- 客戶端拿到返回的 Token,存儲到 local storage 或本地數據庫;
- 下次客戶端再次發起請求,將 Token 附加到 header 中;
- 服務端獲取 header 中的 Token ,經過相同的算法對 Token 中的用戶名和所屬角色進行相同的加密驗證,若是驗證結果相同,則說明這個請求是正常的,沒有被篡改。這個過程能夠徹底不涉及到查詢 Redis 或其餘存儲;
優勢
- 使用 json 做爲數據傳輸,有普遍的通用型,而且體積小,便於傳輸;
- 不須要在服務器端保存相關信息;
- jwt 載荷部分能夠存儲業務相關的信息(非敏感的),例如用戶信息、角色等;
總結
綜上所述,JWT 能夠做爲首選的認證方案。固然,具體的狀況具體分析,還要看是否是適合真實的應用場景。除了上述的這些,涉及到信息安全的,建議所有采用 https 方式部署,採用 https 方式,信息很難被嗅探破解,對應用的安全性很重要。
參考信息:
OAuth: http://www.ruanyifeng.com/blo...
JWT:https://jwt.io/introduction/ http://blog.leapoahead.com/20...
JWT Java 庫: https://github.com/jwtk/jjwt
能夠關注個人公衆號