一起聊-聊token認證
網際網路概念的token認證,大抵是在RESTful API 流行後提出的,在開始token認證之前,我們先梳理下常見的網際網路認證機制。
一、HTTP Basic AuthHTTP Basic Auth常見的有兩種:第一種就是最常見的,即我們在登陸一些web頁面時,會讓我們輸入使用者名稱密碼;另一種是將使用者名稱密碼資訊通過base64這類演算法變換成一條字串在http請求頭中增加auth欄位,再傳輸給服務端。
這個屬於最原始級的認證,缺點比較明顯,存在http頭中的密碼資訊容易被抓包獲取,使用者名稱密碼後服務端後需要查詢資料庫裡的資訊,進行比對資訊,這也增加了伺服器的負擔。
二、session+cookie模式假設目前我們有一個查詢類的web站點,不可能查詢都要登陸一次,為解決一次登陸,可以在固定一段時間內都免登陸查詢,就出現了session+cookie模式,該模式是第一次登陸時使用HTTP Basic Auth,認證成功後,為避免每次都到資料庫裡校驗使用者名稱密碼資訊,就在主機上儲存一份登陸的session資訊,在本身cookie裡記錄對應的session資訊,cookie裡同時儲存expire time。
該模式優缺點都比較明顯:session資訊需要額外的資料庫儲存,例如一般需增加redis、memached等應用。在多機負載時,需要考慮session共享;但好處也是明顯的,session資訊統一管理,可以在服務端統一控制認證的過期時間或個別使用者的過期時間。
token認證最常用的應用場景就是查詢介面的呼叫(RESTful API),查詢介面的資訊在沒有安全需求時,大家都可以通過get方法或post方法取得所需資訊。但在有安全需要時一般需要認證後才能獲取所需的資訊,這時候可以通過先能過HTTP Basic Auth,HTTP Basic Auth認證完成後,服務端返回給客戶端一個類似於UUID的唯一標識,我們稱之為token。該token一般可以在URL或head頭裡加入,如以下的常見的URL模式
http://api,361way.com/getinfo?token=xxxxx 或 http://api,361way.com/getinfo?t=xxxxx ,後面再加上相應的查詢資訊,就可以獲取到相應的資料。
token的好處是服務端不需要儲存相應資訊,但被不懷好意的人從中間獲取到該資訊時,也容易被利用,非法獲取資料。
由於這個簡單的token返回串裡未返回相應的過期時間資訊,如果想增強安全性,一般可以在服務端生成時配合時間戳生成,服務端在接收到client發來帶token的資訊時,先檢測反解token獲取時間戳資訊,如果該時間戳在超過某個時間點時,就認為過期,需要重新獲取。
四、OAuth認證OAuth(開放授權)是一個開放的授權標準,允許使用者讓第三方應用訪問該使用者在某一web服務上儲存的私密的資源(如照片,視訊,聯絡人列表),而無需將使用者名稱和密碼提供給第三方應用。OAuth允許使用者提供一個令牌,而不是使用者名稱和密碼來訪問他們存放在特定服務提供者的資料。每一個令牌授權一個特定的第三方系統(例如,視訊編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相簿中的視訊)。這樣,OAuth讓使用者可以授權第三方網站訪問他們儲存在另外服務提供者的某些特定資訊,而非所有內容。
這個理解起來比較繞口,舉個例子,如很多網站上面有qq或微信登陸介面,qq或微信提供的就是OAuth認證。OAuth雖然名字很洋氣,其本質還是token認證,仔細研究下上面的話,是不是原理上和上面提到的簡單token認證類似,只不過其加了幾個callback函式而已
這裡以douban豆瓣網呼叫QQ的OAuth節口為例,其呼叫方式如下:
# 發起認證: http://www.douban.com/leadToAuthorize # 重定向到QQ認證,並指定回撥: http://www.qq.com/authorize?callback=www.douban.com/callback # 返回授權碼,並callback到douban http://www.douban.com/callback五、JWT認證
JSON Web Token(JWT)是一個非常輕巧的規範。這個規範允許我們使用JWT在使用者和伺服器之間傳遞安全可靠的資訊。一個JWT實際上就是一個字串,它由三部分組成,頭部(Header)、載荷(Payload)與簽名(Signature)。這裡只簡單說下理論,會另開博文深層討論。
Payload裡存放的是儲存簽發者、簽發時間、過期時間、一些資料資訊的JSON格式的內容。
{ "iss": "Online JWT Builder", "iat": 1416797419, "exp": 1448333419, "aud": "www.example.com", "sub": "[email protected]", "GivenName": "Johnny", "Surname": "Rocket", "Email": "[email protected]", "Role": [ "Manager", "Project Administrator" ] }
Header裡指定存放的是指定使用的協議JWT、加密簽名的型別,示例如下:
{ "typ": "JWT", "alg": "HS256" }
最後簽名就是將上面兩者的資訊通過BASE64編碼,再加上金鑰資訊,三者之間通過點號連線,就組合成的JWT token。可以對比簡單token和JWT的區別,兩者本質上都是token,只不過JWT在token裡多傳輸了一些資訊。