一、好久好久之前,Web 基本上就是文檔的瀏覽而已, 既然是瀏覽,做爲服務器, 不須要記錄誰在某一段時間裏都瀏覽了什麼文檔,每次請求都是一個新的HTTP協議, 就是請求加響應, 尤爲是我不用記住是誰剛剛發了HTTP請求, 每一個請求對我來講都是全新的。這段時間很嗨皮。web
二、可是隨着交互式Web應用的興起,像在線購物網站,須要登陸的網站等等,立刻就面臨一個問題,那就是要管理會話,必須記住哪些人登陸系統, 哪些人往本身的購物車中放商品, 也就是說我必須把每一個人區分開,這就是一個不小的挑戰,由於HTTP請求是無狀態的,因此想出的辦法就是給你們發一個會話標識(session id), 說白了就是一個隨機的字串,每一個人收到的都不同, 每次你們向我發起HTTP請求的時候,把這個字符串給一併捎過來, 這樣我就能區分開誰是誰了面試
三、這樣你們很嗨皮了,但是服務器就不嗨皮了,每一個人只須要保存本身的session id,而服務器要保存全部人的session id !若是訪問服務器多了, 就得由成千上萬,甚至幾十萬個。算法
這對服務器說是一個巨大的開銷 , 嚴重的限制了服務器擴展能力, 好比說我用兩個機器組成了一個集羣, 小F經過機器A登陸了系統, 那session id會保存在機器A上, 假設小F的下一次請求被轉發到機器B怎麼辦?機器B可沒有小F的 session id啊。跨域
有時候會採用一點小伎倆: session sticky , 就是讓小F的請求一直粘連在機器A上, 可是這也無論用, 要是機器A掛掉了, 還得轉到機器B去。瀏覽器
那隻好作session 的複製了, 把session id 在兩個機器之間搬來搬去, 快累死了。安全
後來有個叫Memcached的支了招:把session id 集中存儲到一個地方, 全部的機器都來訪問這個地方的數據, 這樣一來,就不用複製了, 可是增長了單點失敗的可能性, 要是那個負責session 的機器掛了, 全部人都得從新登陸一遍, 估計得被人罵死。性能優化
也嘗試把這個單點的機器也搞出集羣,增長可靠性, 但無論如何, 這小小的session 對我來講是一個沉重的負擔服務器
四、因而有人就一直在思考, 我爲何要保存這可惡的session呢, 只讓每一個客戶端去保存該多好?cookie
但是如果不保存這些session id , 怎麼驗證客戶端發給個人session id 的確是我生成的呢? 若是不去驗證,咱們都不知道他們是否是合法登陸的用戶, 那些不懷好意的傢伙們就能夠僞造session id , 隨心所欲了。session
嗯,對了,關鍵點就是驗證 !
好比說, 小F已經登陸了系統, 我給他發一個令牌(token), 裏邊包含了小F的 user id, 下一次小F 再次經過Http 請求訪問個人時候, 把這個token 經過Http header 帶過來不就能夠了。
不過這和session id沒有本質區別啊, 任何人均可以能夠僞造, 因此我得想點兒辦法, 讓別人僞造不了。
那就對數據作一個簽名吧, 好比說我用HMAC-SHA256 算法,加上一個只有我才知道的密鑰, 對數據作一個簽名, 把這個簽名和數據一塊兒做爲token , 因爲密鑰別人不知道, 就沒法僞造token了。
這個token 我不保存, 當小F把這個token 給我發過來的時候,我再用一樣的HMAC-SHA256 算法和一樣的密鑰,對數據再計算一次簽名, 和token 中的簽名作個比較, 若是相同, 我就知道小F已經登陸過了,而且能夠直接取到小F的user id , 若是不相同, 數據部分確定被人篡改過, 我就告訴發送者:對不起,沒有認證。
Token 中的數據是明文保存的(雖然我會用Base64作下編碼, 但那不是加密), 仍是能夠被別人看到的, 因此我不能在其中保存像密碼這樣的敏感信息。
固然, 若是一我的的token 被別人偷走了, 那我也沒辦法, 我也會認爲小偷就是合法用戶, 這其實和一我的的session id 被別人偷走是同樣的。
這樣一來, 我就不保存session id 了, 我只是生成token , 而後驗證token , 我用個人CPU計算時間獲取了個人session 存儲空間 !
解除了session id這個負擔, 能夠說是無事一身輕, 個人機器集羣如今能夠輕鬆地作水平擴展, 用戶訪問量增大, 直接加機器就行。這種無狀態的感受實在是太好了!
cookie 是一個很是具體的東西,指的就是瀏覽器裏面能永久存儲的一種數據,僅僅是瀏覽器實現的一種數據存儲功能。
cookie由服務器生成,發送給瀏覽器,瀏覽器把cookie以kv形式保存到某個目錄下的文本文件內,下一次請求同一網站時會把該cookie發送給服務器。因爲cookie是存在客戶端上的,因此瀏覽器加入了一些限制確保cookie不會被惡意使用,同時不會佔據太多磁盤空間,因此每一個域的cookie數量是有限的。
session 從字面上講,就是會話。這個就相似於你和一我的交談,你怎麼知道當前和你交談的是張三而不是李四呢?對方確定有某種特徵(長相等)代表他就是張三。
session 也是相似的道理,服務器要知道當前發請求給本身的是誰。爲了作這種區分,服務器就要給每一個客戶端分配不一樣的「身份標識」,而後客戶端每次向服務器發請求的時候,都帶上這個「身份標識」,服務器就知道這個請求來自於誰了。至於客戶端怎麼保存這個「身份標識」,能夠有不少種方式,對於瀏覽器客戶端,你們都默認採用 cookie 的方式。
服務器使用session把用戶的信息臨時保存在了服務器上,用戶離開網站後session會被銷燬。這種用戶信息存儲方式相對cookie來講更安全,但是session有一個缺陷:若是web服務器作了負載均衡,那麼下一個操做請求到了另外一臺服務器的時候session會丟失。
在Web領域基於Token的身份驗證隨處可見。在大多數使用Web API的互聯網公司中,tokens 是多用戶下處理認證的最佳方式。
如下幾點特性會讓你在程序中使用基於Token的身份驗證
那些使用基於Token的身份驗證的大佬們
大部分你見到過的API和Web應用都使用tokens。例如Facebook, Twitter, Google+, GitHub等。
在介紹基於Token的身份驗證的原理與優點以前,不妨先看看以前的認證都是怎麼作的。
咱們都是知道HTTP協議是無狀態的,這種無狀態意味着程序須要驗證每一次請求,從而辨別客戶端的身份。
在這以前,程序都是經過在服務端存儲的登陸信息來辨別請求的。這種方式通常都是經過存儲Session來完成。
隨着Web,應用程序,已經移動端的興起,這種驗證的方式逐漸暴露出了問題。尤爲是在可擴展性方面。
在這些問題中,可擴展行是最突出的。所以咱們有必要去尋求一種更有行之有效的方法。
基於Token的身份驗證是無狀態的,咱們不將用戶信息存在服務器或Session中。
這種概念解決了在服務端存儲信息時的許多問題
NoSession意味着你的程序能夠根據須要去增減機器,而不用去擔憂用戶是否登陸。
基於Token的身份驗證的過程以下:
每一次請求都須要token。token應該在HTTP的頭部發送從而保證了Http請求無狀態。咱們一樣經過設置服務器屬性Access-Control-Allow-Origin:* ,讓服務器能接受到來自全部域的請求。
須要主要的是,在ACAO頭部標明(designating)*時,不得帶有像HTTP認證,客戶端SSL證書和cookies的證書。
實現思路:
當咱們在程序中認證了信息並取得token以後,咱們便能經過這個Token作許多的事情。
咱們甚至能基於建立一個基於權限的token傳給第三方應用程序,這些第三方程序可以獲取到咱們的數據(固然只有在咱們容許的特定的token)
無狀態、可擴展
在客戶端存儲的Tokens是無狀態的,而且可以被擴展。基於這種無狀態和不存儲Session信息,負載負載均衡器可以將用戶信息從一個服務傳到其餘服務器上。
若是咱們將已驗證的用戶的信息保存在Session中,則每次請求都須要用戶向已驗證的服務器發送驗證信息(稱爲Session親和性)。用戶量大時,可能會形成一些擁堵。
可是不要着急。使用tokens以後這些問題都迎刃而解,由於tokens本身hold住了用戶的驗證信息。
安全性
請求中發送token而再也不是發送cookie可以防止CSRF(跨站請求僞造)。即便在客戶端使用cookie存儲token,cookie也僅僅是一個存儲機制而不是用於認證。不將信息存儲在Session中,讓咱們少了對session操做。
token是有時效的,一段時間以後用戶須要從新驗證。咱們也不必定須要等到token自動失效,token有撤回的操做,經過token revocataion可使一個特定的token或是一組有相同認證的token無效。
可擴展性
Tokens可以建立與其它程序共享權限的程序。例如,能將一個隨便的社交賬號和本身的大號(Fackbook或是Twitter)聯繫起來。當經過服務登陸Twitter(咱們將這個過程Buffer)時,咱們能夠將這些Buffer附到Twitter的數據流上(we are allowing Buffer to post to our Twitter stream)。
使用tokens時,能夠提供可選的權限給第三方應用程序。當用戶想讓另外一個應用程序訪問它們的數據,咱們能夠經過創建本身的API,得出特殊權限的tokens。
多平臺跨域
咱們提早先來談論一下CORS(跨域資源共享),對應用程序和服務進行擴展的時候,須要介入各類各類的設備和應用程序。
Having our API just serve data, we can also make the design choice to serve assets from a CDN. This eliminates the issues that CORS brings up after we set a quick header configuration for our application.
只要用戶有一個經過了驗證的token,數據和資源就可以在任何域上被請求到。
Access-Control-Allow-Origin: *
基於標準建立token的時候,你能夠設定一些選項。咱們在後續的文章中會進行更加詳盡的描述,可是標準的用法會在JSON Web Tokens體現。
最近的程序和文檔是供給JSON Web Tokens的。它支持衆多的語言。這意味在將來的使用中你能夠真正的轉換你的認證機制。
合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!