天天看點

vue token 過期要在哪重新請求_Cookie、Session和 Token

Session

伺服器隻有一台,用戶端卻有千千萬。怎麼能夠讓伺服器知道目前請求服務的是哪台用戶端呢?我們舉個生活中的例子:

你去圖書館(服務端)借書(請求服務)。先得辦卡(登入擷取session_id)吧,放兜裡(cookie)。去刷卡處刷卡看看卡是不是僞造的,看看卡裡的資訊和資料庫比對下看看有沒有過期等等(檢查session_id是否被篡改,是否失效根據session_id查詢下記憶體或者資料庫(通常是記憶體資料庫)裡對應的有沒有過期)。過期不給進重新辦卡(重新登入認證),沒過期就給進(傳回你請求的結果)

是以咯流程就是這樣子:

當 client通過使用者名密碼請求server并通過身份認證後,server就會生成身份認證相關的 session 資料,并且儲存在記憶體或者記憶體資料庫。并将對應的 sesssion_id傳回給client,client會把儲存session_id(可以加密簽名下防止篡改)在cookie。此後client的所有請求都會附帶該session_id(畢竟預設會把cookie傳給server),以确定server是否存在對應的session資料以及檢驗登入狀态,權限啦巴拉巴拉……如果通過校驗就該幹嘛幹嘛,否則重新登入咯。

前端退出的話就清cookie。後端強制前端重新認證的話就清除或者修改session。

Session是對于服務端來說的,用戶端是沒有Session一說的。Session是伺服器在和用戶端建立連接配接時添加用戶端連接配接标志,最終會在伺服器軟體(Apache、Tomcat、JBoss)轉化為一個臨時Cookie發送給給用戶端,當用戶端第一請求時伺服器會檢查是否攜帶了這個Session(臨時Cookie),如果沒有則會添加Session,如果有就拿出這個Session來做相關操作。

在這裡引用别人家的一個小故事來加深印象:

         在說session是啥之前,我們先來說說為什麼會出現session會話,它出現的機理是什麼?    我們知道,我們用浏覽器打開一個網頁,用到的是HTTP協定,了解計算機的應該都知道這個協定,它是無狀态的,什麼是無狀态呢?就是說這一次請求和上一次請求是沒有任何關系的,互不認識的,沒有關聯的。但是這種無狀态的的好處是快速。是以就會帶來一個問題就是,我希望幾個請求的頁面要有關聯,比如:我在www.a.com/login.php裡面登陸了,我在www.a.com/index.php 也希望是登陸狀态,但是,這是2個不同的頁面,也就是2個不同的HTTP請求,這2個HTTP請求是無狀态的,也就是無關聯的,是以無法單純的在index.php中讀取到它在login.php中已經登陸了!        那咋搞呢?我不可能這2個頁面我都去登陸一遍吧。或者用笨方法這2個頁面都去查詢資料庫,如果有登陸狀态,就判斷是登陸的了。這種查詢資料庫的方案雖然可行,但是每次都要去查詢資料庫不是個事,會造成資料庫的壓力。是以正是這種訴求,這個時候,一個新的用戶端存儲資料方式出現了:cookie。cookie是把少量的資訊存儲在使用者自己的電腦上,它在一個域名下是一個全局的,隻要設定它的存儲路徑在域名www.a.com下 ,那麼當使用者用浏覽器通路時,php就可以從這個域名的任意頁面讀取cookie中的資訊。是以就很好的解決了我在www.a.com/login.php頁面登陸了,我也可以在www.a.com/index.php擷取到這個登陸資訊了。同時又不用反複去查詢資料庫。雖然這種方案很不錯,也很快速友善,但是由于cookie 是存在使用者端,而且它本身存儲的尺寸大小也有限,最關鍵是使用者可以是可見的,并可以随意的修改,很不安全。那如何又要安全,又可以友善的全局讀取資訊呢?于是,這個時候,一種新的存儲會話機制:session 誕生了。      Session 就是在一次會話中解決2次HTTP的請求的關聯,讓它們産生聯系,讓2兩個頁面都能讀取到找個這個全局的session資訊。session資訊存在于伺服器端,是以也就很好的解決了安全問題

Token :

token是使用者身份的驗證方式,我們通常叫它:令牌。最簡單的token組成:uid(使用者唯一的身份辨別)、time(目前時間的時間戳)、sign(簽名,由token的前幾位+鹽以雜湊演算法壓縮成一定長的十六進制字元串,可以防止惡意第三方拼接token請求伺服器)。還可以把不變的參數也放進token,避免多次查庫。

應用場景:

A:當使用者首次登入成功(注冊也是一種可以适用的場景)之後, 伺服器端就會生成一個 token 值,這個值,會在伺服器儲存token值(儲存在資料庫中),再将這個token值傳回給用戶端.

B:用戶端拿到 token 值之後,進行本地儲存。(SP存儲是大家能夠比較支援和易于了解操作的存儲)

C:當用戶端再次發送網絡請求(一般不是登入請求)的時候,就會将這個 token 值附帶到參數中發送給伺服器.

D:伺服器接收到用戶端的請求之後,會取出token值與儲存在本地(資料庫)中的token值做對比

對比一:如果兩個 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和 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的狀态是存儲在用戶端。

vue token 過期要在哪重新請求_Cookie、Session和 Token

JWT

這裡就不介紹jwt的三部分組成、由什麼組成、怎麼生成加密了。

日常的舉個生活中的例子吧:

你去遊樂園(服務端)玩耍(請求服務)。先得買門票(登入擷取token)吧,放兜裡(cookie、header……)。去檢票口檢票看看票有沒有過期(檢查token是否失效)。過期不給進重新買票(重新登入認證),沒過期就給進(傳回你請求的結果)

有沒有覺得和Session有什麼不一樣?server不用存儲資訊了。一切都存在用戶端。個人覺得這就是最大的不同。

這裡大緻列下倆者差別,一些比如JWT更簡單、APP對支援不易的一些已經解決或者細究覺得很扯的或者大同小異的不在此列

Session JWT
安全性 得考慮CSRF攻擊
存儲 需要倆端都存儲
可控性 服務端可随時修改權限….

Json Web Token(JWT)

JWT 是一個開放标準(RFC 7519),它定義了一種用于簡潔,自包含的用于通信雙方之間以 JSON 對象的形式安全傳遞資訊的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。它具備兩個特點:

  • 簡潔(Compact)

    可以通過URL, POST 參數或者在 HTTP header 發送,因為資料量小,傳輸速度快

  • 自包含(Self-contained)

    負載中包含了所有使用者所需要的資訊,避免了多次查詢資料庫

什麼時候你應該用JSON Web Tokens

下列場景中使用JSON Web Token是很有用的:

  • Authorization (授權) : 這是使用JWT的最常見場景。一旦使用者登入,後續每個請求都将包含JWT,允許使用者通路該令牌允許的路由、服務和資源。單點登入是現在廣泛使用的JWT的一個特性,因為它的開銷很小,并且可以輕松地跨域使用。
  • Information Exchange (資訊交換) : 對于安全的在各方之間傳輸資訊而言,JSON Web Tokens無疑是一種很好的方式。因為JWTs可以被簽名,例如,用公鑰/私鑰對,你可以确定發送人就是它們所說的那個人。另外,由于簽名是使用頭和有效負載計算的,您還可以驗證内容沒有被篡改。

JSON Web Token的結構是什麼樣的

vue token 過期要在哪重新請求_Cookie、Session和 Token

JSON Web Token由三部分組成,它們之間用圓點(.)連接配接。這三部分分别是:

  • Header
  • Payload
  • Signature

是以,一個典型的JWT看起來是這個樣子的:

xxxxx.yyyyy.zzzzz

看一張官網的圖就明白了:

vue token 過期要在哪重新請求_Cookie、Session和 Token

JWT 組成

vue token 過期要在哪重新請求_Cookie、Session和 Token
  • Header 頭部

頭部包含了兩部分,token 類型和采用的加密算法

{ "alg": "HS256", "typ": "JWT" }

它會使用 Base64 編碼組成 JWT 結構的第一部分,如果你使用Node.js,可以用Node.js的包base64url來得到這個字元串。

Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它并不是一種加密過程。
  • Payload 負載

這部分就是我們存放資訊的地方了,你可以把使用者 ID 等資訊放在這裡,JWT 規範裡面對這部分有進行了比較詳細的介紹,常用的由 iss(簽發者),exp(過期時間),sub(面向的使用者),aud(接收方),iat(簽發時間)。

{ "iss": "lion1ou JWT", "iat": 1441593502, "exp": 1441594722, "aud": "www.example.com", "sub": "[email protected]" }

同樣的,它會使用 Base64 編碼組成 JWT 結構的第二部分

  • Signature 簽名

前面兩部分都是使用 Base64 進行編碼的,即前端可以解開知道裡面的資訊。Signature 需要使用編碼後的 header 和 payload 以及我們提供的一個密鑰,然後使用 header 中指定的簽名算法(HS256)進行簽名。簽名的作用是保證 JWT 沒有被篡改過。

三個部分通過

.

連接配接在一起就是我們的 JWT 了,它可能長這個樣子,長度貌似和你的加密算法和私鑰有關系。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

.

eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ

.

PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

其實到這一步可能就有人會想了,HTTP 請求總會帶上 token,這樣這個 token 傳來傳去占用不必要的帶寬啊。如果你這麼想了,那你可以去了解下 HTTP2,HTTP2 對頭部進行了壓縮,相信也解決了這個問題。

  • 簽名的目的

最後一步簽名的過程,實際上是對頭部以及負載内容進行簽名,防止内容被竄改。如果有人對頭部以及負載的内容解碼之後進行修改,再進行編碼,最後加上之前的簽名組合形成新的JWT的話,那麼伺服器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的。如果要對新的頭部和負載進行簽名,在不知道伺服器加密時用的密鑰的話,得出來的簽名也是不一樣的。

  • 資訊暴露

在這裡大家一定會問一個問題:Base64是一種編碼,是可逆的,那麼我的資訊不就被暴露了嗎?

是的。是以,在JWT中,不應該在負載裡面加入任何敏感的資料。在上面的例子中,我們傳輸的是使用者的User ID。這個值實際上不是什麼敏感内容,一般情況下被知道也是安全的。但是像密碼這樣的内容就不能被放在JWT中了。如果将使用者的密碼放在了JWT中,那麼懷有惡意的第三方通過Base64解碼就能很快地知道你的密碼了。

是以JWT适合用于向Web應用傳遞一些非敏感資訊。JWT還經常用于設計使用者認證和授權系統,甚至實作Web應用的單點登入。

JSON Web Tokens是如何工作的

  1. 應用(或者用戶端)想授權伺服器請求授權。例如,如果用授權碼流程的話,就是/oauth/authorize
  2. 當授權被許可以後,授權伺服器傳回一個access token給應用
  3. 應用使用access token通路受保護的資源(比如:API)
vue token 過期要在哪重新請求_Cookie、Session和 Token
vue token 過期要在哪重新請求_Cookie、Session和 Token
  1. 首先,前端通過Web表單将自己的使用者名和密碼發送到後端的接口。這一過程一般是一個HTTP POST請求。建議的方式是通過SSL加密的傳輸(https協定),進而避免敏感資訊被嗅探。
  2. 後端核對使用者名和密碼成功後,将使用者的id等其他資訊作為JWT Payload(負載),将其與頭部分别進行Base64編碼拼接後簽名,形成一個JWT。形成的JWT就是一個形同lll.zzz.xxx的字元串。
  3. 後端将JWT字元串作為登入成功的傳回結果傳回給前端。前端可以将傳回的結果儲存在localStorage或sessionStorage上,登出時前端删除儲存的JWT即可。
  4. 前端在每次請求時将JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題)
  5. 後端檢查是否存在,如存在驗證JWT的有效性。例如,檢查簽名是否正确;檢查Token是否過期;檢查Token的接收方是否是自己(可選)。
  6. 驗證通過後後端使用JWT中包含的使用者資訊進行其他邏輯操作,傳回相應結果。

和Session方式存儲id的差異

Session方式存儲使用者id的最大弊病在于Session是存儲在伺服器端的,是以需要占用大量伺服器記憶體,對于較大型應用而言可能還要儲存許多的狀态。一般而言,大型應用還需要借助一些KV資料庫和一系列緩存機制來實作Session的存儲。

而JWT方式将使用者狀态分散到了用戶端中,可以明顯減輕服務端的記憶體壓力。除了使用者id之外,還可以存儲其他的和使用者相關的資訊,例如該使用者是否是管理者、使用者所在的分組等。雖說JWT方式讓伺服器有一些計算壓力(例如加密、編碼和解碼),但是這些壓力相比磁盤存儲而言可能就不算什麼了。具體是否采用,需要在不同場景下用資料說話。

  • 單點登入

Session方式來存儲使用者id,一開始使用者的Session隻會存儲在一台伺服器上。對于有多個子域名的站點,每個子域名至少會對應一台不同的伺服器,例如:

www.taobao.com

nv.taobao.com

nz.taobao.com

login.taobao.com

。是以如果要實作在

login.taobao.com

登入後,在其他的子域名下依然可以取到Session,這要求我們在多台伺服器上同步Session。使用JWT的方式則沒有這個問題的存在,因為使用者的狀态已經被傳送到了用戶端。

總結

JWT的主要作用在于(一)可附帶使用者資訊,後端直接通過JWT擷取相關資訊。(二)使用本地儲存,通過HTTP Header中的Authorization位送出驗證。但其實關于JWT存放到哪裡一直有很多讨論,有人說存放到本地存儲,有人說存 cookie。個人偏向于放在本地存儲,如果你有什麼意見和看法歡迎提出。

綜上所述:

1、Cookie:儲存在用戶端,不是很安全;

2、Session:儲存在伺服器端,并生成一個Session id儲存在用戶端。通路過多時會占用伺服器的記憶體和性能;

3、Token:首次登陸後,伺服器生成Token值,儲存在資料庫中,再将這個Token值傳回給用戶端。增加資料庫的存儲和查詢壓力;

4、JWT(Json Web Token):前後端分離項目中使用。根據算法生成,儲存在本地。消耗伺服器的計算壓力。