在作接口測試時,常常會碰到請求參數爲token的類型,可是可能大部分測試人員對token,cookie,session的區別仍是隻知其一;不知其二。mysql
cookie 是一個很是具體的東西,指的就是瀏覽器裏面能永久存儲的一種數據,僅僅是瀏覽器實現的一種數據存儲功能。web
cookie由服務器生成,發送給瀏覽器,瀏覽器把cookie以kv形式保存到某個目錄下的文本文件內,下一次請求同一網站時會把該cookie發送給服務器。因爲cookie是存在客戶端上的,因此瀏覽器加入了一些限制確保cookie不會被惡意使用,同時不會佔據太多磁盤空間,因此每一個域的cookie數量是有限的。redis
session 從字面上講,就是會話。這個就相似於你和一我的交談,你怎麼知道當前和你交談的是張三而不是李四呢?對方確定有某種特徵(長相等)代表他就是張三。算法
session 也是相似的道理,服務器要知道當前發請求給本身的是誰。爲了作這種區分,服務器就要給每一個客戶端分配不一樣的「身份標識」,而後客戶端每次向服務器發請求的時候,都帶上這個「身份標識」,服務器就知道這個請求來自於誰了。至於客戶端怎麼保存這個「身份標識」,能夠有不少種方式,對於瀏覽器客戶端,你們都默認採用 cookie 的方式。sql
服務器使用session把用戶的信息臨時保存在了服務器上,用戶離開網站後session會被銷燬。這種用戶信息存儲方式相對cookie來講更安全,但是session有一個缺陷:若是web服務器作了負載均衡,那麼下一個操做請求到了另外一臺服務器的時候session會丟失。數據庫
Token的引入:Token是在客戶端頻繁向服務端請求數據,服務端頻繁的去數據庫查詢用戶名和密碼並進行對比,判斷用戶名和密碼正確與否,並做出相應提示,在這樣的背景下,Token便應運而生。後端
Token的定義:Token是服務端生成的一串字符串,以做客戶端進行請求的一個令牌,當第一次登陸後,服務器生成一個Token便將此Token返回給客戶端,之後客戶端只需帶上這個Token前來請求數據便可,無需再次帶上用戶名和密碼。最簡單的token組成:uid(用戶惟一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以哈希算法壓縮成必定長的十六進制字符串,能夠防止惡意第三方拼接token請求服務器)。api
使用Token的目的:Token的目的是爲了減輕服務器的壓力,減小頻繁的查詢數據庫,使服務器更加健壯。瀏覽器
HTTP 是一種沒有狀態的協議,也就是它並不知道是誰是訪問應用。這裏咱們把用戶當作是客戶端,客戶端使用用戶名還有密碼經過了身份驗證,不過下回這個客戶端再發送請求時候,還得再驗證一下。安全
解決的方法就是,當用戶請求登陸的時候,若是沒有問題,咱們在服務端生成一條記錄,這個記錄裏能夠說明一下登陸的用戶是誰,而後把這條記錄的 ID 號發送給客戶端,客戶端收到之後把這個 ID 號存儲在 Cookie 裏,下次這個用戶再向服務端發送請求的時候,能夠帶着這個 Cookie ,這樣服務端會驗證一個這個 Cookie 裏的信息,看看能不能在服務端這裏找到對應的記錄,若是能夠,說明用戶已經經過了身份驗證,就把用戶請求的數據返回給客戶端。
上面說的就是 Session,咱們須要在服務端存儲爲登陸的用戶生成的 Session ,這些 Session 可能會存儲在內存,磁盤,或者數據庫裏。咱們可能須要在服務端按期的去清理過時的 Session 。
使用基於 Token 的身份驗證方法,在服務端不須要存儲用戶的登陸記錄。大概的流程是這樣的:
APP登陸的時候發送加密的用戶名和密碼到服務器,服務器驗證用戶名和密碼,若是成功,以某種方式好比隨機生成32位的字符串做爲token,存儲到服務器中,並返回token到APP,之後APP請求時,凡是須要驗證的地方都要帶上該token,而後服務器端驗證token,成功返回所須要的結果,失敗返回錯誤信息,讓他從新登陸。其中服務器上token設置一個有效期,每次APP請求的時候都驗證token和有效期。
那麼個人問題來了: 1.服務器上的token存儲到數據庫中,每次查詢會不會很費時。若是不存儲到數據庫,應該存儲到哪裏呢。 2.客戶端獲得的token確定要加密存儲的,發送token的時候再解密。存儲到數據庫仍是配置文件呢?
token是個易失數據,丟了無非讓用戶從新登陸一下,新浪微博動不動就讓我從新登陸,反正這事兒我是無所謂啦。
因此若是你以爲普通的數據庫表撐不住了,能夠放到 MSSQL/MySQL 的內存表裏(不過聽說mysql的內存表性能提高有限),能夠放到 Memcache裏(講真,這個是挺常見的策略),能夠放到redis裏(我作過這樣的實現),甚至能夠放到 OpenResty 的變量字典裏(只要你有信心不爆內存)。
token是個憑條,不過它比門票溫柔多了,門票丟了從新花錢買,token丟了從新操做下認證一個就能夠了,所以token丟失的代價是能夠忍受的——前提是你別丟太頻繁,要是讓用戶隔三差五就認證一次那就損失用戶體驗了。
基於這個出發點,若是你認爲用數據庫來保持token查詢時間太長,會成爲你係統的瓶頸或者隱患,能夠放在內存當中。
好比memcached、redis,KV方式很適合你對token查詢的需求。
這個不會太佔內存,好比你的token是32位字符串,要是你的用戶量在百萬級或者千萬級,那纔多少內存。
要是數據量真的大到單機內存扛不住,或者以爲一宕機全丟風險大,只要這個token生成是足夠均勻的,高低位切一下分到不一樣機器上就行,內存絕對不會是問題。
客戶端方面這個除非你有一個很是安全的辦法,好比操做系統提供的隱私數據存儲,那token確定會存在泄露的問題。好比我拿到你的手機,把你的token拷出來,在過時以前就均可以以你的身份在別的地方登陸。
解決這個問題的一個簡單辦法
一、在存儲的時候把token進行對稱加密存儲,用時解開。
二、將請求URL、時間戳、token三者進行合併加鹽簽名,服務端校驗有效性。
這兩種辦法的出發點都是:竊取你存儲的數據較爲容易,而反彙編你的程序hack你的加密解密和簽名算法是比較難的。然而其實說難也不難,因此終究是防君子不防小人的作法。話說加密存儲一個你要是被人扒開客戶端看也不會被噴明文存儲……
方法1它拿到存儲的密文解不開、方法2它不知道你的簽名算法和鹽,二者能夠結合食用。
可是若是token被人拷走,他天然也能植入到本身的手機裏面,那到時候他的手機也能夠以你的身份來用着,這你就瞎了。
因而能夠提供一個讓用戶能夠主動expire一個過去的token相似的機制,在被盜的時候能遠程止損。
在網絡層面上token明文傳輸的話會很是的危險,因此建議必定要使用HTTPS,而且把token放在post body裏。
補充:
cookie與session的區別
一、cookie數據存放在客戶端上,session數據放在服務器上。
二、cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙
考慮到安全應當使用session。
三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能
考慮到減輕服務器性能方面,應當使用COOKIE。
四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。
五、因此我的建議:
將登錄信息等重要信息存放爲SESSION
其餘信息若是須要保留,能夠放在COOKIE中
session與token的區別
session 和 oauth token並不矛盾,做爲身份認證 token安全性比session好,由於每一個請求都有簽名還能防止監聽以及重放攻擊,而session就必須靠鏈路層來保障通信安全了。如上所說,若是你須要實現有狀態的會話,仍然能夠增長session來在服務器端保存一些狀態
App一般用restful api跟server打交道。Rest是stateless的,也就是app不須要像browser那樣用cookie來保存session,所以用session token來標示本身就夠了,session/state由api server的邏輯處理。 若是你的後端不是stateless的rest api, 那麼你可能須要在app裏保存session.能夠在app裏嵌入webkit,用一個隱藏的browser來管理cookie session.
Session 是一種HTTP存儲機制,目的是爲無狀態的HTTP提供的持久機制。所謂Session 認證只是簡單的把User 信息存儲到Session 裏,由於SID 的不可預測性,暫且認爲是安全的。這是一種認證手段。 而Token ,若是指的是OAuth Token 或相似的機制的話,提供的是 認證 和 受權 ,認證是針對用戶,受權是針對App 。其目的是讓 某App有權利訪問 某用戶 的信息。這裏的 Token是惟一的。不能夠轉移到其它 App上,也不能夠轉到其它 用戶 上。 轉過來講Session 。Session只提供一種簡單的認證,即有此 SID,即認爲有此 User的所有權利。是須要嚴格保密的,這個數據應該只保存在站方,不該該共享給其它網站或者第三方App。 因此簡單來講,若是你的用戶數據可能須要和第三方共享,或者容許第三方調用 API 接口,用 Token 。若是永遠只是本身的網站,本身的 App,用什麼就無所謂了。
打破誤解:
「只要關閉瀏覽器 ,session就消失了?」
不對。對session來講,除非程序通知服務器刪除一個session,不然服務器會一直保留,程序通常都是在用戶作log off的時候發個指令去刪除session。
然而瀏覽器歷來不會主動在關閉以前通知服務器它將要關閉,所以服務器根本不會有機會知道瀏覽器已經關閉,之因此會有這種錯覺,是大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器後這個session id就消失了,再次鏈接服務器時也就沒法找到原來的session。若是服務器設置的cookie被保存在硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然可以打開原來的session.
偏偏是因爲關閉瀏覽器不會致使session被刪除,迫使服務器爲session設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就能夠覺得客戶端已經中止了活動,纔會把session刪除以節省存儲空間。
方案 SSESION:我發給你一張身份證,但只是一張寫着身份證號碼的紙片。你每次來辦事,我去後臺查一下你的 id 是否是有效。 方案 TOKEN :我發給你一張加密的身份證,之後你只要出示這張卡片,我就知道你必定是本身人。