⑴ Token是什麼和session、cookie相比,使用場景有什麼區別
在Web開發領域,相信大家對於Cookie和Session都很熟悉,Cookie和Session都是會話保持技術的解決方案。隨著技術的發展,Token機制出現在我們面前,不過很多開發者對於Token和Cookie、Session的區別及使用場景分辨不清。
Cookie和Session的用途 要知道我們訪問網站都是通過HTTP協議或HTTPS協議來完成的, HTTP協議它本身是無狀態的協議 (即:伺服器無法分辨哪些請求是來源於同個客戶)。而業務層面會涉及到客戶端與伺服器端的交互(同網站下多個頁面間能共享數據),此時伺服器端必須要保持會話狀態,這樣才能進行用戶身份的鑒別。
由於HTTP無狀態的特性,如果要實話客戶端和伺服器端的會話保持,那就需要其它機制來實現,於是Cookie和Session應運而生。
通常情況下, Session和Cookie是搭配在一起使用的 。
Token是什麼上面說到的Session和Cookie機制來保持會話,會存在一個問題:客戶端瀏覽器只要保存自己的SessionID即可,而 伺服器卻要保存所有用戶的Session信息,這對於伺服器來說開銷較大,而且不利用伺服器的擴展 (比如伺服器集群時,Session如何同步存儲就是個問題)!
於是有人思考,如果把Session信息讓客戶端來保管而且無法偽造不就可以解決這個問題了?進而有了Token機制。
Token俗稱為「令牌」 ,它的構成是:
Token機制下的認證流程 Token機制其實和Cookie機制極其相似 ,主要有以下流程:
1、用戶登錄進行身份認證,認證成功後伺服器端生成Token返回給客戶端;
2、客戶端接收到Token後保存在客戶端(可保存在Cookie、LocalStorage、SessionStorage中);
3、客戶端再次請求伺服器端時,將Token作為請求頭放入Headers中;
4、伺服器端接收請求頭中的Token,將用戶參數按照既定規則再進行一次簽名,兩次簽名若一致則認為成功,反之數據存在篡改請求失敗。
(生成簽名示例圖)
(驗證簽名示例圖)
Token與Cookie+Session的區別Cookie其實也充當的是令牌作用,但它是「有狀態」的; 而Token令牌是無狀態的,更利於分布式部署。
session和cookie
在講Token之前,先簡單說說什麼是session和cookie。
Token
但是這里會有個問題, 伺服器要保存所有用戶的session信息,開銷會很大,如果在分布式的架構下,就需要考慮session共享的問題,需要做額外的設計和開發 ,例如把session中的信息保存到Redis中進行共享;所以因為這個原因,有人考慮這些信息是否可以讓客戶端保存,可以保存到任何地方,並且保證其安全性,於是就有了Token。
Token是服務端生成的一串字元串,可以看做客戶端進行請求的一個令牌。
基於Token的認證流程
整體的流程是這樣的:
總結 希望我的回答,能夠幫助到你!我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。
Token顧名思義就是令牌、憑證、鑰匙 。只有這把鑰匙,你才能打開門。token一般都是服務端生成,比如一個web系統,用戶登錄的時候,服務端校驗用戶名密碼通過以後,會生成一個token,同時會生成refreshToken和一個過期時間。然後將refreshToken和token返回給客戶端。客戶端會將token保存下來。後續所有的請求都會攜帶這個token。服務端會判斷當前token是否存在已經是否過期。如果token不存在或者過期就會拒絕本次請求。如果token過期怎麼辦,就用refreshToken刷新時間。當然這里可能還有別的方案。比如只生成token,每次請求的時候都刷新過期時間。如果長時間沒有刷新過期時間,那token就會過期。
session就是回話,這是服務端的一種操作。當你第一次訪問一個web網站的時候,服務端會生成一個session,並有一個sessionid和他對應。這個session是存儲到內存中的,你可以向這個session中寫入信息,比如當前登錄用戶的信息。sessionid會被返回到客戶端,客戶端一般採用cookie來保存。當然這個cookie不用人為寫入。用tomcat容器來舉個例子。 當後端調用HttpServletRequest對象的getSession的方法的時候,tomcat內部會生成一個jsessonid(tomcat sessionid的叫法)。這個jsessonid會隨本次請求返回給客戶端。響應頭信息
這個jessionid就會寫到cookie中。之後jessionid就會通過cookie傳遞到服務端。
這里我們就會很清楚了, session的數據是存儲到內存中。那問題就來了,如果我們的服務是分布式部署,有多台機器的話,可能我們第一次登陸的時候,我們把用戶的信息存儲到了session,但是後面的請求到了B機器上,那B機器是獲取不到用戶的session的。另外就是session存儲在內存中,那伺服器重啟,session就丟失了,這就是他的弊端。現在有一些技術,例如session共享、iphash、session持久等也可以解決上述問題 。
cookie是瀏覽器的一種策略。上述講到了sessionid就是存儲在cookie中的。我們知道http協議是無狀態的,cookie就是用來解決這個問題的。cookie中可以用來保存服務端返回的一些用戶信息的,例如前文提到的token、sessionid。每一次的請求,都會攜帶這些cookie。服務端從請求頭中取到cookie中的信息,就可以識別本次請求的來源,這樣,http是不是就變成有狀態的了。
這里說幾點cookie注意事項。
1、cookie存放在客戶端,所以是不安全的。人為可以清除
2、cookie有過期時間設定。如果不設置過期時間,說明這個cookie就是當前瀏覽器的會話時間,瀏覽器關了,cookie 就存在了。如果有過期時間,cookie就會存儲到硬碟上,瀏覽器關閉不影響cookie。下次打開瀏覽器,cookie還存在
3、cookie有大小的限制,4KB。
這個問題,網上有很多的答案,相信都看過了,估計也沒有看明白。所以我就不去網上復制了,用自己的話,盡量說通俗,說重點。
cookie和session實際上是同一套認證流程,相輔相成。session保存在伺服器,cookie保存在客戶端。最常見的做法就是客戶端的cookie僅僅保存一個sessionID,這個sessionID是一個毫無規則的隨機數,由伺服器在客戶端登錄通過後隨機生產的。往後,客戶端每次訪問該網站都要帶上這個由sessionID組成的cookie。伺服器收到請求,首先拿到客戶端的sessionID,然後從伺服器內存中查詢它所代表的客戶端(用戶名,用戶組,有哪些許可權等)。
與token相比,這里的重點是,伺服器必須保存sessionID以及該ID所代表的客戶端信息。這些內容可以保存在內存,也可以保存到資料庫(通常是內存資料庫)。
而token則可以伺服器完全不用保存任何登錄信息。
token的流程是這樣的。客戶端登錄通過後,伺服器生成一堆客戶端身份信息,包括用戶名、用戶組、有那些許可權、過期時間等等。另外再對這些信息進行簽名。之後把身份信息和簽名作為一個整體傳給客戶端。這個整體就叫做token。之後,客戶端負責保存該token,而伺服器不再保存。客戶端每次訪問該網站都要帶上這個token。伺服器收到請求後,把它分割成身份信息和簽名,然後驗證簽名,若驗證成功,就直接使用身份信息(用戶名、用戶組、有哪些許可權等等)。
可以看出,相對於cookie/session機制,token機制中,伺服器根本不需要保存用戶的身份信息(用戶名、用戶組、許可權等等)。這樣就減輕了伺服器的負擔。
我們舉個例來說,假如目前有一千萬個用戶登錄了,在訪問不同的網頁。如果用cookie/session,則伺服器內存(或內存資料庫)中要同時記錄1千萬個用戶的信息。每次客戶端訪問一個頁面,伺服器都要從內存中查詢出他的登錄信息。而如果用token,則伺服器內存中不記錄用戶登錄信息。它只需要在收到請求後,直接使用客戶端發過來的登錄身份信息。
可以這么說, cookie/session是伺服器說客戶端是誰,客戶端才是誰。而token是客戶端說我(客戶端)是誰,我就是誰 。當然了,token是有簽名機制的。要是客戶端偽造身份,簽名通不過。這個簽名演算法很簡單,就是將客戶端的身份信息加上一個只有伺服器知道的鹽值(不能泄露),然後進行md5散列演算法(這里只是簡化,方便理解,實際細節要稍復雜一些)。
cookie/session在單伺服器,單域名時比較簡單,否則的話,就要考慮如何將客戶端的session保存或同步到多個伺服器。還要考慮一旦宕機,內存中的這些信息是否會丟失。token因為伺服器不保存用戶身份,就不存在這個問題。這是token的優點。
token因為伺服器不保存用戶身份信息,一切都依賴當初那個簽名。所以存在被盜用的風險。也就是說一旦盜用,伺服器可能毫無辦法,因為它只認簽名演算法。而session機制,伺服器看誰不爽,可以隨時把他踢出(從內存中刪掉)。正是因為如此,token高度依賴過期時間。過期時間不能太長。過期短,可以減少被盜用的風險。
除了上面所說的,我個人認為,如果開發的系統足夠小,傾向於使用cookie/session。如果系統同時登錄用戶多,集群伺服器多,有單點登錄需求,則傾向於使用token。
萬維網的發展 歷史
Token, 令牌,代表執行某些操作的權利的對象。
token主要用於鑒權使用,主要有以下幾類:
cookie主要是網站用於在瀏覽器臨時存放的數據,包括瀏覽器緩存數據以及伺服器設定的一些數據,主要存放在瀏覽器端。
session主要用於保存會話數據,一般存儲在伺服器端,同時每一條session對用一個sessionID,sessionID是存放在瀏覽器的cookie中。
傳統上的會話登陸和鑒權主要用session加cookie實現,隨著分布式系統的快速演進,尤其是微服務的應用,token+cookie的授權訪問機製得到親睞,通常在用戶登錄後,伺服器生成訪問令牌(Access token),瀏覽器存儲cookie中,在每次請求資源時都會在請求頭中帶上token,用於伺服器授權訪問使用。
Token和session都是web網站的會話保持、認證的解決方案;
既然都一樣為什麼還有token的說法。
從token產生的背景說起1.移動端應用使得伺服器端Session失效
2.分布式系統中Session無法共享
所以說session對於以上兩種情況無效了,所以有了Token的說法
那麼什麼是token,token長什麼樣子?先給大家一個直觀的感受
token:PC-3066014fa0b10792e4a762-23-20170531133947-4f6496
說白了token保存就是用戶的信息(不能保存密碼等敏感信息)
token的組成:
客戶端標識-USERCODE-USERID-CREATIONDATE-RONDEM[6位]
USERCODE,RONDEM[6位]經過MD5加密就變成了以上字元串
token的請求流程
請求流程解析
1.前端用戶發送登錄信息至認證系統
2.驗證用戶登錄信息,判斷用戶是否存在
3.如果用戶存在,生成token信息(客戶端標識-USERCODE-USERID-CREATIONDATE-RONDEM[6位]),並存儲在redis中
4.並將該token返回前端,附加至header
驗證token客戶端
將token附加至header
服務端
最後總結一下
一般的垂直架構項目使用Session沒有任何問題,但是分布式項目或涉及到移動端則考慮使用token。
session
session的中文翻譯是「會話」,當用戶打開某個web應用時,便與web伺服器產生一次session。伺服器使用session把用戶的信息臨時保存在了伺服器上,用戶離開網站後session會被銷毀。這種用戶信息存儲方式相對cookie來說更安全,可是session有一個缺陷:如果web伺服器做了負載均衡,那麼下一個操作請求到了另一台伺服器的時候session會丟失。
cookie
cookie是保存在本地終端的數據。cookie由伺服器生成,發送給瀏覽器,瀏覽器把cookie以kv形式保存到某個目錄下的文本文件內,下一次請求同一網站時會把該cookie發送給伺服器。由於cookie是存在客戶端上的,所以瀏覽器加入了一些限制確保cookie不會被惡意使用,同時不會占據太多磁碟空間,所以每個域的cookie數量是有限的。
cookie的組成有:名稱(key)、值(value)、有效域(domain)、路徑(域的路徑,一般設置為全局:"")、失效時間、安全標志(指定後,cookie只有在使用SSL連接時才發送到伺服器(https))。下面是一個簡單的js使用cookie的例子:
用戶登錄時產生cookie:
document.cookie = "id="+result.data['id']+"; path=/";
document.cookie = "name="+result.data['name']+"; path=/";
document.cookie = "avatar="+result.data['avatar']+"; path=/";
使用到cookie時做如下解析:
var cookie = document.cookie;var cookieArr = cookie.split(";");var user_info = {};for(var i = 0; i < cookieArr.length; i++) {
user_info[cookieArr[i].split("=")[0]] = cookieArr[i].split("=")[1];
}
$('#user_name').text(user_info[' name']);
$('#user_avatar').attr("src", user_info[' avatar']);
$('#user_id').val(user_info[' id']);
token
token的意思是「令牌」,是用戶身份的驗證方式,最簡單的token組成:uid(用戶唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以哈希演算法壓縮成一定長的十六進制字元串,可以防止惡意第三方拼接token請求伺服器)。還可以把不變的參數也放進token,避免多次查庫
cookie 和session的區別
1、cookie數據存放在客戶的瀏覽器上,session數據放在伺服器上。
2、cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙
考慮到安全應當使用session。
3、session會在一定時間內保存在伺服器上。當訪問增多,會比較佔用你伺服器的性能
考慮到減輕伺服器性能方面,應當使用COOKIE。
4、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
5、所以個人建議:
將登陸信息等重要信息存放為SESSION
其他信息如果需要保留,可以放在COOKIE中
token 和session 的區別
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,用什麼就無所謂了。
token就是令牌,比如你授權(登錄)一個程序時,他就是個依據,判斷你是否已經授權該軟體;cookie就是寫在客戶端的一個txt文件,裡麵包括你登錄信息之類的,這樣你下次在登錄某個網站,就會自動調用cookie自動登錄用戶名;session和cookie差不多,只是session是寫在伺服器端的文件,也需要在客戶端寫入cookie文件,但是文件里是你的瀏覽器編號.Session的狀態是存儲在伺服器端,客戶端只有session id;而Token的狀態是存儲在客戶端。
想要全面深入地掌握Token,我們需要先了解這些:Token的概念、身份驗證過程、實現思路、使用場景,以及Cookie、Session、Token的區別。
Token是驗證用戶身份的一種方式,簡稱做「令牌」。最簡單的token組成:uid(用戶唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽,以哈希演算法壓縮成一定長的十六進制字元串,可以防止惡意第三方拼接token請求伺服器)。還可以把不變的參數也放進token,避免多次查庫。
每一次請求都需要Token,Token應該在HTTP的頭部發送,從而保證Http請求無狀態。我們同樣通過設置伺服器屬性Access-Control-Allow-Origin:* ,讓伺服器能接受到來自所有域的請求。
需要注意的是,在ACAO頭部標明(designating)*時,不得帶有像HTTP認證,客戶端SSL證書和cookies的證書。
當我們在程序中認證了信息,並取得Token之後,我們便能通過這個Token做許多的事情。我們甚至能基於創建一個基於許可權的token傳給第三方應用程序,這些第三方程序能夠獲取到我們的數據(當然只有在我們允許的特定的token)。
Cookie和Session的區別
綜合以上考量,建議方案:
Session和Cookie取長補短、配合使用,將登陸信息等重要信息存放為Session,其他信息如果需要保留,可以放在Cookie中。
Session和Token並不矛盾,作為身份認證,Token安全性比Session高,因為Token發送的每個請求都帶有簽名,能防止監聽,以及重放攻擊。而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的不可預測性,暫且認為是安全的,這是一種認證手段。
Session只提供一種簡單的認證,即有此SID,以及User的全部權利。是需要嚴格保密的,這個數據只在使用站點保存,不可共享給其它網站或者第三方App。所以簡單來說,如果你的用戶數據可能需要和第三方共享,或者允許第三方調用API介面,則使用Token,如果只是自己的網站或App應用,使用什麼都OK。
Token,指的是OAuth Token或類似的機制的話,提供的是認證和授權 ,認證是針對用戶,授權是針對App。其目的是讓某App有權利訪問某用戶的信息,這里的Token是唯一的,不可以轉移到其它App上,也不可以轉到其它用戶上。
Token就是令牌,比如你授權(登錄)一個程序時,他就是個依據,判斷你是否已經授權該軟體。Cookie就是寫在客戶端的一個txt文件,記錄下用戶的訪問、登錄等信息,下次用戶再登錄某個網站時,伺服器接收到請求,就會自動調用Cookie,自動登錄用戶名。
Session和Cookie差不多,只是Session是寫在伺服器端的文件,也需要在客戶端寫入Cookie文件,但是文件里是用戶的瀏覽器編號.Session的狀態是存儲在伺服器端,客戶端只有session id,而Token的狀態是存儲在客戶端的。
以上,是關於Token、Session、Cookie的知識點介紹,更加深入的詳解,感興趣的童鞋,可查看我持續分享的【BAT架構技術專題合集500+】,回復【架構】,即可領取。
Token是什麼?
Token是令牌、憑證、鑰匙,在Web領域中進行 身份驗證 ,關鍵點在驗證!!,說驗證就必須了解一下Web領域的發展史呢。
2. 隨著人們需求的改變,比如在線購物系統,需要登陸的網站等,這時候需要進行 交互 性,伺服器接收到請求的時候,要根據你是否登陸,以及判斷你是誰,來給你響應,這時候問題就來了,怎麼知道每次請求的誰呢,所以就出來了一個 會話標識(session id),就是一個隨機的字元串 ,每個人登陸的時候,伺服器都會返回一個會話標識,這是再請求的時候,只要帶上會話標識,伺服器就知道請求的是誰。
3. 這樣子每個人只要保存自己的session id就可以啦,伺服器要保存 所有人 的session id!!!如果有成千上萬的人訪問伺服器,那對伺服器是巨大的開銷,嚴重限制了伺服器端的擴展能力,比如機器A跟機器B組成了伺服器集群,那麼訪問了機器A,會話標識在機器A上,如果轉到機器B,就不能訪問了,也許會說,那復制呢,機器A搬到機器B,也有說統一把標識放在一個機器上,但是萬一這個機器掛了呢,那體驗就很差了。
4. 這個時候就有人想,用戶自己保存自己的標識,就是Token,訪問的時候帶上這個Token,這個 Token是用戶id+簽名 ,驗證時,伺服器只要相同的演算法和伺服器才知道的密鑰進行簽名,如果結果跟Token中的簽名一樣,那就可以證明是登陸過的用戶。
這樣一來,伺服器不保存session id,只要生成Token,訪問時,只要對Token進行判斷,Token也是有有效期的,所以也要進行refreshToken的。
Token,Cookie,Session三者使用場景的區別?Token主要是Web領域的身份認證 ,最常見的就是Web API這個功能:
Cookie 就是餅干, 它是伺服器生產,永久保存在瀏覽器的數據,以kv的形式 ,你可以打開你的瀏覽器(這里以win10 edge為例),點擊上方的三個點的按鈕,再點擊更多工具,再點擊開發人員工具,再點擊網路,此時內容選擇文檔,然後刷新頁面,找Cookie即可。
Session是會話標識,是伺服器用來判斷正在會話的用戶是誰,伺服器生產的隨機數 ,保存在伺服器中,用戶端也要進行保存,雖然能實現會話的共能,但對伺服器的擴展能力限制,同時當伺服器是兩台機器組成以上的時候,會導致兩台機器以上保存的session同步問題,會導致用戶體驗極差。
Token跟Session最大的區別就是Token服務端不用保存,同時是通過簽名等技術實現的,Session因為是隨機數,導致伺服器要進行保存。
⑵ 自動化token過期場景如何設計用例
自動化token過期場景如何設計用例有三種方案:
1、每一次請求都進行重新生成一個新的token頻率過高,性能不好。
2、每次登錄的時候生成兩個token給前端進行返回,一個是用於鑒別用戶身份的token,另外一個token則是用於刷新token用的。
3、登錄過後給前端進行返回token並設置了過期時間30分鍾,每次請求的時候前端把token存在請求頭裡面進行發請求,後端接收請求的時候獲取請求頭出來進行jwt解析判斷過期時間是否小於10分鍾,如果小於10分鍾就生成新的token在responseHearde進行。
⑶ token什麼意思 前端如何使用token
大家好,從網上找了很多關於token的文章,都是提到要生成一個token,然後前端每次請求的時候,要使用這個token,請問下如何在前端使用生成的token?
前端能就使用jQuery搞定,還是需要其他的前端框架配合?能有這方面的完整示例嗎?
做後端的,對前端的東西有些不太懂,請見諒
先謝謝大家了!!
解決方案1:
一般是後端有個結構給你拿token的,然後你請求的時候,根據約定
把token
放在header中
放uri參數中
放body表單里
給後端
解決方案2:
因為http協議是無狀態的 token是後台給你發的一個唯一標識 你再去訪問後台時帶上這個token 後台就知道你是誰了
同session的作用
解決方案3:
前台生成的token,可能會存在安全性問題吧
解決方案4:
你做後台應該很了解token才對呀。
用戶登錄後,生成一個session_id,即token,可以存在redis里。然後前端或客戶端保存起來,存cookie或者LS都行,然後所有的請求作為基類參數帶上(也有通過cookie帶的),然後server端再取到後,驗證你是不是你。
解決方案5:
使用領域很多,以表單為例子:
後台生成token.
前端列印表單,並且講該token變成隱藏項。<input type="hide" value="{{token}}">
客戶提交表單。
後台驗證提交的token合法性。
驗證成功,處理表單。驗證失敗,返回錯誤處理頁面。
解決方案6:
token一般都是後端生成的,在登陸之後返回,前端保存token,之後每次請求都帶上token來驗證身份。
解決方案7:
問題是前端生成的token給後台有用嗎
解決方案8:
一般token都是伺服器端生成,做csrf的。我在補充下我見過前端生成的栗子,雖然沒啥卵用,但讓我廢了好大的勁才發現。
譬如你有一個驗證碼的表單,你在傳遞驗證碼的時候,新增一個隱藏域,將驗證碼用你本地的js加密後,作為參數傳遞,這樣在伺服器端可以檢測驗證碼是不是被篡改過。
但這樣沒啥卵用,因為在提交的時候用同樣的js模擬即可。
解決方案9:
大多數情況下,token作為一種令牌,都是在伺服器端生成,生成的方法很多,從簡單點的對時間或者id或者兩個混合起來進行哈希運算的值到自己設計更復雜的演算法都可以,生成的目的是為了給前端下一次通信時使用這個token作為令牌,當作為一個請求資源的許可的標識,而伺服器則會視這個token在一段時間內都是有效的,並且還可以額外看情況加上是否是同一個ip之類的其它的限制,從而防止某種資源被非法訪問
偶有前端(包括本地客戶端或者app)生成token的情況是已經約定好了一個好的加密機制,伺服器可以信任客戶端的這個輸入的情況下可以由前端或者客戶端生成
⑷ NodeJS(Express框架)實現 Token 驗證免密登錄 (一)
看文章之前,強烈建議先把項目拉取下來!案例來自小弟的開源項目 「項目Github」
文章內容只是個人學習的一些總結經驗,不具有權威性,這是 Node 服務端的實現,後面會寫前端的實現
常見的 Token 驗證方式種:
推薦閱讀:
JWT 超詳細分析
說一說幾種常用的登錄認證方式,你用的哪種
推薦閱讀:
JSON Web Token 入門教程
JSON Web Token - 在Web應用間安全地傳遞信息
首先我們先安裝 jsonwebtoken 和 express-jwt 這兩個中間件
jsonwebtoken : 用於生成 Token 。它也有解析 Token 的功能
express-jwt : 用於解析 Token(比 jsonwebtoken 解決方便) , 它把解析之後的數據,存放到 requset.user 中
如果你看了上面 JWT 介紹的文章,就知道 JWT 是由三部分組成的,分別是 載荷(Payload) 、 頭部(Header) 、 簽名(Signature) 。
jsonwebtoken 給我們提供了 sign(payload, secretOrPrivateKey, [options, callback]) 方法。sign 方法對應的其實就是 JWT 簽名(Signature) 的動作
payload:荷載 ,參數類型:對象secretOrPrivateKey:自定義的密鑰,密鑰屬於敏感信息。參數類型:字元串options:可以配置 header 、荷載、指定演算法類型。參數類型:對象callback:回調
眼尖的朋友應該發現, payload 和 options 兩個 參數 都可以配置荷,下面有例子。根據自己的習慣選擇就好
Payload 部分 JWT 規定了7個官方欄位,這些欄位都是可選欄位。可直接以對象的形式傳給 payload 參數。
options 中也可以接受以上七個欄位,不過欄位名稱有所區別。
除此之後 options 提供了 algorithm 和 header ,分別對應使用的加密演算法和 JWT 的 Header 部分,其實 algorithm 應該也是屬於 Header 部分的。
說了這么多,其實我們一般常用的只有 exp(expiresIn) 和 algorithm 這兩個欄位,
例子一:
token 的有效時間是配置在 option 里
例子二:
我們也可以在 payload 里配置有效時間
jsonwebtoken 除了生成 token 外,還提供了解析驗證 token 的方法, jwt.verify(token, secretOrPublicKey, [options, callback]) 。
這里就不演示了, 感興趣的朋友可以參考文檔: 「JsonWebToken」
express-jwt 是針對 express 框架開發的 JWT Token 驗證中間件。我先來簡單說以下它的用法。
主要有兩種方式,一種是哪些請求需要驗證就往哪裡加驗證;另外一種是先給全部請求加上驗證,再給不需要驗證的請求配置 白名單 。
方式一:
看完上面的例子,很顯然不符合我們的逾期,一個正常的項目有個幾十個 api 是分分鍾的事。我們不可能一個個給他加上檢驗
方式二:
這種方式是不是方便很多,而且更美觀,維護起來也更方便
Token 解析出來的用戶信息,默認存放在 req.user , 可以直接 req.user.userId 來使用生成 Token 時填進去的用戶id
你也通過 requestProperty 和 resultProperty 來設置用戶信息存放的對象。
這里就不展開,詳細文檔參考: express-jwt
可以使用 app.use() 來注冊處理驗證不通過的情況
到這里 Token 的生成、驗證、檢驗不通過錯誤處理就完成了。 Token 生成一般是在登錄之後生成,並返回給前端,前端拿到 Token ,並在每次請求 api 的時候攜帶上 Token , Token 就相當於這個用戶的身份,不要輕易泄露。
Token一旦簽發,不能主動讓它失效,只能等待它有效期過才能失效。也就是說就算你修改了密碼,之前的 Token 也還是有效的。你可以修改後端生成 Token 時使用的密鑰,不讓之前的 Token 檢驗通過,但是這就表示之前所有生成 Token 都失效了,做不到針對某個用戶進行注銷。這顯然也不合適的。 所以用戶修改密碼時,前端一般都要清除之前保存的 Token,再重獲取新的 Token
有朋友應該會想到在後端把 Token 儲存起來,每一個用戶對應一個 token。修改賬號時,再生成一個新的 Token 覆蓋之前的 Token,但這就違背了使用 Token 的目的,Token 的使用很大程度就為了減少伺服器的壓力。把盡可能多的信息存儲在客戶端而不是服務端。
使用 Token 可以防禦 CSRF 攻擊,之前寫過一篇關於網路安全的文章,感興趣的朋友可以看一下 「XSS 攻擊、CSRF 攻擊、SQL 注入、流量劫持(DNS 劫持、HTTP 劫持)—— 瀏覽器安全」
⑸ 鑒權操作流程(前端邏輯)
1.用戶登錄 調取介面 去獲取對應的token,此時將token 存儲在了sessionStorage中。項目的最開始是去獲取當前用戶的token。(base64加密),之後調用token有效時間和校驗token是否失效。
2.公共請求方法 request 函數在請求頭添加 token,即每次的相關請求都帶有了當前用戶的token信息,如果token在有效期內則可以正常請求。否則便會拋出異常。
3.假如token的有效時間是3600s,但是用戶很久沒有操作系統,會啟動用戶鎖定狀態,通過監控用戶的操作時間差來判斷鎖定的狀態。正常情況下token是不會過期的,因為在token的過期前幾分鍾內會進行token的更新操作,理論上token是不會過期的。所以當用戶重新操作系統的時候,超過了一定時間之後需要用戶重新登錄系統來,其實也是調取的token的介面,去獲取新的token,並替換之前的token。(但是這里沒有考慮到的一種情況是如果項目一直在啟動,但是服務重啟了,或者其他原因導致前端的token在驗證的時候不通過,這樣就會導致頁面的鎖定狀態無法打開,這時候前端做的處理是重新跳轉到登錄頁,並刪除token,就像第一次登錄系統一樣。)
⑹ JWT token封裝以及自動刷新方案建議
什麼是JWT
pom.xml
JWTUtil.java
用戶登錄操作
在前後分離場景下,越來越多的項目使用jwt token作為介面的安全機制,但存在jwt過期後,用戶無法直接感知,假如在用戶操作頁面期間,突然提示登錄,則體驗很不友好,所以就有了token自動刷新需求;
方案:前端控制檢測token,無感知刷新
用戶登錄成功的時候,一次性給他兩個Token,分別為AccessToken和RefreshToken
AccessToken有效期較短,比如1天或者5天,用於正常請求
RefreshToken有效期可以設置長一些,例如10天、20天,作為刷新AccessToken的憑證
刷新方案:當AccessToken即將過期的時候,例如提前30分鍾,客戶端利用RefreshToken請求指定的API獲取新的AccessToken並更新本地存儲中的AccessToken
核心邏輯
1、登錄成功後,jwt生成AccessToken; UUID生成RefreshToken並存儲在服務端redis中,設置過期時間
2、介面返回3個欄位AccessToken/RefreshToken/訪問令牌過期時間戳
3、由於RefreshToken存儲在服務端redis中,假如這個RefreshToken也過期,則提示重新登錄;
老王的疑問:RefreshToken有效期那麼長,和直接將AccessToken的有效期延長有什麼區別
答:RefreshToken不像AccessToken那樣在大多數請求中都被使用,主要是本地檢測accessToken快過期的時候才使用,
一般本地存儲的時候,也不叫refreshToken,前端可以取個別名,混淆代碼讓攻擊者不能直接識別這個就是刷新令牌
缺點:前端每次請求需要判斷token距離過期時間
優點:後端壓力小,代碼邏輯改動不大
刷新token方法未實現。
⑺ 無感刷新token
需求
當token過期的時候,刷新token,前端需要做到無感刷新token,即刷token時要做到用戶無感知,避免頻繁登錄。實現思路
方法一
後端返回過期時間,前端判斷token過期時間,去調用刷新token介面
缺點:需要後端額外提供一個token過期時間的欄位;使用了本地時間判斷,若本地時間被篡改,特別是本地時間比伺服器時間慢時,攔截會失敗。
方法二(可行)
寫個定時器,定時刷新token介面
缺點:浪費資源,消耗性能,不建議採用。
方法三 (推薦)
在響應攔截器中攔截,判斷token 返回過期後,調用刷新token介面
思考:
我在遇到同樣問題的時候也是考慮了兩種方法,一種是定時刷新一種是過期時刷新。 但是我選擇了定時刷新的方案。 假如token 的過期時間是5分鍾,那麼在高頻率使用的情況下(每秒訪問介面)每隔5分鍾就會刷新一次token。如果web端有大屏展示頁面的話,過期刷新的方案跟定時刷新的方案調用的token次數其實一樣。但過期刷新的時候可能會阻礙介面的請求,導致每隔5分鍾會出現一次介面變慢的情況。 測試下發現,用定時刷新的方案並不會浪費資源,唯一的代價就是需要運行一個定時器。
後端每個需要token的介面,都返回token的失效時間指的是定時器的時間也是後端返回token失效的時間
實現:
axios的基本骨架,利用service.interceptors.response進行攔截
importaxiosfrom'
axios'service.interceptors.response.use(response=>
{
if(response.data.code ===409) {
returnrefreshToken({
refreshToken:localStorage.getItem('refreshToken'),token: getToken() })
.then(res=> {
const{ token } = res.data
setToken(token)
response.headers.Authorization =`${token}`}).catch(err=> {
removeToken()
router.push('/login')
returnPromise.reject(err)
}) }
return response && response.data },(error) =>{
Message.error(error.response.data.msg)
returnPromise.reject(error)
})
⑻ JWT生成token及過期處理方案
## 業務場景
在前後分離場景下,越來越多的項目使用token作為介面的安全機制,APP端或者WEB端(使用VUE、REACTJS等構建)使用token與後端介面交互,以達到安全的目的。本文結合stackoverflow以及本身項目實踐,試圖總結出一個通用的,可落地的方案。
## 基本思路
- 單個token
1. token(A)過期設置為15分鍾
2. 前端發起請求,後端驗證token(A)是否過期;如果過期,前端發起刷新token請求,後端設置已再次授權標記為true,請求成功
3. 前端發起請求,後端驗證再次授權標記,如果已經再次授權,則拒絕刷新token的請求,請求成功
4. 如果前端每隔72小時,必須重新登錄,後端檢查用戶最後一次登錄日期,如超過72小時,則拒絕刷新token的請求,請求失敗
- 授權token加上刷新token
用戶僅登錄一次,用戶改變密碼,則廢除token,重新登錄
## 1.0實現
1.登錄成功,返回access\_token和refresh\_token,客戶端緩存此兩種token;
2.使用access_token請求介面資源,成功則調用成功;如果token超時,客戶端
攜帶refresh\_token調用中間件介面獲取新的access\_token;
3.中間件接受刷新token的請求後,檢查refresh_token是否過期。
如過期,拒絕刷新,客戶端收到該狀態後,跳轉到登錄頁;
如未過期,生成新的access\_token和refresh\_token並返回給客戶端(如有可能,讓舊的refresh\_token失效),客戶端攜帶新的access\_token重新調用上面的資源介面。
4.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(使access\_token和refresh\_token失效),同時清空客戶端的access\_token和refresh\_toke。
後端表
id user\_id client\_id client\_secret refresh\_token expire\_in create\_date del_flag
## 2.0實現
場景: access\_token訪問資源 refresh\_token授權訪問 設置固定時間X必須重新登錄
1.登錄成功,後台jwt生成access\_token(jwt有效期30分鍾)和refresh\_token(jwt有效期15天),並緩存到redis(hash-key為token,sub-key為手機號,value為設備唯一編號(根據手機號碼,可以人工廢除全部token,也可以根據sub-key,廢除部分設備的token。),設置過期時間為1個月,保證最終所有token都能刪除),返回後,客戶端緩存此兩種token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果token超時,中間件刪除access\_token(廢除);客戶端再次攜帶refresh\_token調用中間件介面獲取新的access_token;
3.中間件接受刷新token的請求後,檢查refresh_token是否過期。
如過期,拒絕刷新,刪除refresh_token(廢除); 客戶端收到該狀態後,跳轉到登錄頁;
如未過期,檢查緩存中是否有refresh\_token(是否被廢除),如果有,則生成新的access\_token並返回給客戶端,客戶端接著攜帶新的access_token重新調用上面的資源介面。
4.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access\_token和refresh\_token(廢除)),同時清空客戶端側的access\_token和refresh\_toke。
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
6.以上3刷新access_token可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(拒絕的場景:失效,長時間未登錄,頻繁刷新)
2.0 變動
1.登錄
2.登錄攔截器
3.增加刷新access_token介面
4.退出登錄
5.修改密碼
## 3.0實現
場景:自動續期 長時間未使用需重新登錄
1.登錄成功,後台jwt生成access\_token(jwt有效期30分鍾),並緩存到redis(hash-key為access\_token,sub-key為手機號,value為設備唯一編號(根據手機號碼,可以人工廢除全部token),設置access_token過期時間為7天,保證最終所有token都能刪除),返回後,客戶端緩存此token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果token超時,中間件刪除access\_token(廢除),同時生成新的access\_token並返回。客戶端收到新的access_token,
再次請求介面資源。
3.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access\_token(廢除)),同時清空客戶端側的access\_token。
4.以上2 可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(拒絕的場景:長時間未登錄,頻繁刷新)
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
3.0 變動
1.登錄
2.登錄攔截器
3.退出登錄
4.修改密碼
1.3 場景:token過期重新登錄 長時間未使用需重新登錄
1.登錄成功,後台jwt生成access\_token(jwt有效期7天),並緩存到redis,key為 "user\_id:access\_token",value為access\_token(根據用戶id,可以人工廢除指定用戶全部token),設置緩存過期時間為7天,保證最終所有token都能刪除,請求返回後,客戶端緩存此access_token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果token超時,中間件刪除access\_token(廢除),同時生成新的access\_token並返回。客戶端收到新的access_token,
再次請求介面資源。
3.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access\_token(廢除)),同時清空客戶端側的access\_token。
4.以上2 可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(拒絕的場景:長時間未登錄,頻繁刷新)
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
1.3 變動
1.登錄
2.登錄攔截器
3.退出登錄
4.修改密碼
# 解決方案
2.0 場景: access\_token訪問資源 refresh\_token授權訪問 設置固定時間X必須重新登錄
1.登錄成功,後台jwt生成access\_token(jwt有效期30分鍾)和refresh\_token(jwt有效期15天),並緩
存到redis(hash-key為token,sub-key為手機號,value為設備唯一編號(根據手機號碼,可以人工廢除全
部token,也可以根據sub-key,廢除部分設備的token。),設置過期時間為1個月,保證最終所有token都
能刪除),返回後,客戶端緩存此兩種token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果
token超時,中間件刪除access\_token(廢除);客戶端再次攜帶refresh\_token調用中間件介面獲取新的
access_token;
3.中間件接受刷新token的請求後,檢查refresh_token是否過期。
如過期,拒絕刷新,刪除refresh_token(廢除); 客戶端收到該狀態後,跳轉到登錄頁;
如未過期,檢查緩存中是否有refresh\_token(是否被廢除),如果有,則生成新的access\_token並返回給
客戶端,客戶端接著攜帶新的access_token重新調用上面的資源介面。
4.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access\_token和refresh\_token(
廢除)),同時清空客戶端側的access\_token和refresh\_toke。
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
6.以上3刷新access_token可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(
拒絕的場景:失效,長時間未登錄,頻繁刷新)
2.0 變動
1.登錄
2.登錄攔截器
3.增加刷新access_token介面
4.退出登錄
5.修改密碼
3.0 場景:自動續期 長時間未使用需重新登錄
1.登錄成功,後台jwt生成access_token(jwt有效期30分鍾),並緩存到redis(hash-key為
access_token,sub-key為手機號,value為設備唯一編號(根據手機號碼,可以人工廢除全部token,也可以
根據sub-key,廢除部分設備的token。),設置access_token過期時間為1個月,保證最終所有token都能刪
除),返回後,客戶端緩存此token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果
token超時,中間件刪除access\_token(廢除),同時生成新的access\_token並返回。客戶端收到新的
access_token,
再次請求介面資源。
3.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access_token(廢除)),同時清
空客戶端側的access_token。
4.以上2 可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(拒絕的場景:長
時間未登錄,頻繁刷新)
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
3.0 變動
1.登錄
2.登錄攔截器
3.退出登錄
4.修改密碼
4.0 場景:token過期重新登錄 長時間未使用需重新登錄
1.登錄成功,後台jwt生成access_token(jwt有效期7天),並緩存到redis,key為
"user\_id:access\_token" + 用戶id,value為access_token(根據用戶id,可以人工廢除指定用戶全部
token),設置緩存過期時間為7天,保證最終所有token都能刪除,請求返回後,客戶端緩存此
access_token;
2.使用access\_token請求介面資源,校驗成功且redis中存在該access\_token(未廢除)則調用成功;如果
token超時,中間件刪除access\_token(廢除),同時生成新的access\_token並返回。客戶端收到新的
access_token,
再次請求介面資源。
3.客戶端退出登錄或修改密碼後,調用中間件注銷舊的token(中間件刪除access_token(廢除)),同時清
空客戶端側的access_token。
4.以上2 可以增加根據登錄時間判斷最長X時間必須重新登錄,此時則拒絕刷新token。(拒絕的場景:長
時間未登錄,頻繁刷新)
5.如手機丟失,可以根據手機號人工廢除指定用戶設備關聯的token。
4.0 變動
1.登錄
2.登錄攔截器
3.退出登錄
4.修改密碼
## 最終實現
### 後端
1. 在登錄介面中 如果校驗賬號密碼成功 則根據用戶id和用戶類型創建jwt token(有效期設置為-1,即永不過期),得到A
2. 更新登錄日期(當前時間new Date()即可)(業務上可選),得到B
3. 在redis中緩存key為ACCESS_TOKEN:userId:A(加上A是為了防止用戶多個客戶端登錄 造成token覆蓋),value為B的毫秒數(轉換成字元串類型),過期時間為7天(7 * 24 * 60 * 60)
4. 在登錄結果中返回json格式為{"result":"success","token": A}
5. 用戶在介面請求header中攜帶token進行登錄,後端在所有介面前置攔截器進行攔截,作用是解析token 拿到userId和用戶類型(用戶調用業務介面只需要傳token即可),
如果解析失敗(拋出SignatureException),則返回json(code = 0 ,info= Token驗證不通過, errorCode = '1001');
此外如果解析成功,驗證redis中key為ACCESS_TOKEN:userId:A 是否存在 如果不存在 則返回json(code = 0 ,info= 會話過期請重新登錄, errorCode = '1002');
如果緩存key存在,則自動續7天超時時間(value不變),實現頻繁登錄用戶免登陸。
6. 把userId和用戶類型放入request參數中 介面方法中可以直接拿到登錄用戶信息
7. 如果是修改密碼或退出登錄 則廢除access_tokens(刪除key)
### 前端(VUE)
1. 用戶登錄成功,則把username存入cookie中,key為loginUser;把token存入cookie中,key為accessToken
把token存入Vuex全局狀態中
2. 進入首頁
⑼ 前端請求token過長是什麼原因
原因:java.lang.IllegalArgumentException:Requestheaderistoolarge解決方法:將長Token作為Value,另外生成一個短Token作為key,存入Redis中,返回給瀏覽器短Token,瀏覽器攜帶短Token訪問伺服器,伺服器使用短Token去Redis中取出長Token,解析成實體類。
⑽ 前端的token驗證 (以vue為例)
1、第一次登錄的時候,前端調後端的登陸介面,發送用戶名和密碼
2、後端收到請求,驗證用戶名和密碼,驗證成功,就給前端返回一個token
3、前端拿到token,將token存儲到localStorage和vuex中,並跳轉路由頁面
4、前端每次跳轉路由,就判斷 localStroage 中有無 token ,沒有就跳轉到登錄頁面,有則跳轉到對應路由頁面
5、每次調後端介面,都要在請求頭中加token
6、後端判斷請求頭中有無token,有token,就拿到token並驗證token,驗證成功就返回數據,驗證失敗(例如:token過期)就返回401,請求頭中沒有token也返回401
7、如果前端拿到狀態碼為401,就清除token信息並跳轉到登錄頁面