當前位置:首頁 » 網頁前端 » webtoken安全嗎
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

webtoken安全嗎

發布時間: 2022-12-18 20:31:21

A. 微信小程序token被獲取安全嗎

安全。微信小程序都是經過官方認證,其范圍都在法律范圍之內,因此token被獲取是安全的,微信是騰訊公司於2011年1月21日推出的一款通過網路快速發送語音簡訊、視頻、圖片和文字,支持多人群聊的手機聊天軟體。

B. 來,科普一下JWT

1. JSON Web Token是什麼

JSON Web Token (JWT)是一個開放標准(RFC 7519),它定義了一種緊湊的、自包含的方式,用於作為JSON對象在各方之間安全地傳輸信息。該信息可以被驗證和信任,因為它是數字簽名的。

2. 什麼時候你應該用JSON Web Tokens

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

Authorization (授權) : 這是使用JWT的最常見場景。一旦用戶登錄,後續每個請求都將包含JWT,允許用戶訪問該令牌允許的路由、服務和資源。單點登錄是現在廣泛使用的JWT的一個特性,因為它的開銷很小,並且可以輕松地跨域使用。

Information Exchange (信息交換) : 對於安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。因為JWTs可以被簽名,例如,用公鑰/私鑰對,你可以確定發送人就是它們所說的那個人。另外,由於簽名是使用頭和有效負載計算的,您還可以驗證內容沒有被篡改。

3. JSON Web Token的結構是什麼樣的

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

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

接下來,具體看一下每一部分:

Header

header典型的由兩部分組成:token的類型(「JWT」)和演算法名稱(比如:HMAC SHA256或者RSA等等)。

例如:

然後,用Base64對這個JSON編碼就得到JWT的第一部分

Payload

Public claims : 可以隨意定義。

下面是一個例子:

對payload進行Base64編碼就得到JWT的第二部分

Signature

為了得到簽名部分,你必須有編碼過的header、編碼過的payload、一個秘鑰,簽名演算法是header中指定的那個,然對它們簽名即可。

例如:

簽名是用於驗證消息在傳遞過程中有沒有被更改,並且,對於使用私鑰簽名的token,它還可以驗證JWT的發送方是否為它所稱的發送方。

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

4. JSON Web Tokens是如何工作的

在認證的時候,當用戶用他們的憑證成功登錄以後,一個JSON Web Token將會被返回。此後,token就是用戶憑證了,你必須非常小心以防止出現安全問題。一般而言,你保存令牌的時候不應該超過你所需要它的時間。

無論何時用戶想要訪問受保護的路由或者資源的時候,用戶代理(通常是瀏覽器)都應該帶上JWT,典型的,通常放在Authorization header中,用Bearer schema。

header應該看起來是這樣的:

伺服器上的受保護的路由將會檢查Authorization header中的JWT是否有效,如果有效,則用戶可以訪問受保護的資源。如果JWT包含足夠多的必需的數據,那麼就可以減少對某些操作的資料庫查詢的需要,盡管可能並不總是如此。

如果token是在授權頭(Authorization header)中發送的,那麼跨源資源共享(CORS)將不會成為問題,因為它不使用cookie。

下面這張圖顯示了如何獲取JWT以及使用它來訪問APIs或者資源:

5. 基於Token的身份認證 與 基於伺服器的身份認證

5.1. 基於伺服器的身份認證

在討論基於Token的身份認證是如何工作的以及它的好處之前,我們先來看一下以前我們是怎麼做的:

HTTP協議是無狀態的,也就是說,如果我們已經認證了一個用戶,那麼他下一次請求的時候,伺服器不知道我是誰,我們必須再次認證

傳統的做法是將已經認證過的用戶信息存儲在伺服器上,比如Session。用戶下次請求的時候帶著Session ID,然後伺服器以此檢查用戶是否認證過。

這種基於伺服器的身份認證方式存在一些問題:

Sessions : 每次用戶認證通過以後,伺服器需要創建一條記錄保存用戶信息,通常是在內存中,隨著認證通過的用戶越來越多,伺服器的在這里的開銷就會越來越大。

Scalability : 由於Session是在內存中的,這就帶來一些擴展性的問題。

CORS : 當我們想要擴展我們的應用,讓我們的數據被多個移動設備使用時,我們必須考慮跨資源共享問題。當使用AJAX調用從另一個域名下獲取資源時,我們可能會遇到禁止請求的問題。

CSRF : 用戶很容易受到CSRF攻擊。

5.2. JWT與Session的差異

相同點是,它們都是存儲用戶信息;然而,Session是在伺服器端的,而JWT是在客戶端的。

Session方式存儲用戶信息的最大問題在於要佔用大量伺服器內存,增加伺服器的開銷。

而JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的內存壓力。

Session的狀態是存儲在伺服器端,客戶端只有session id;而Token的狀態是存儲在客戶端。

5.3. 基於Token的身份認證是如何工作的

基於Token的身份認證是無狀態的,伺服器或者Session中不會存儲任何用戶信息。

雖然這一實現可能會有所不同,但其主要流程如下:

注意:

5.4. 用Token的好處

無狀態和可擴展性: Tokens存儲在客戶端。完全無狀態,可擴展。我們的負載均衡器可以將用戶傳遞到任意伺服器,因為在任何地方都沒有狀態或會話信息。

安全: Token不是Cookie。(The token, not a cookie.)每次請求的時候Token都會被發送。而且,由於沒有Cookie被發送,還有助於防止CSRF攻擊。即使在你的實現中將token存儲到客戶端的Cookie中,這個Cookie也只是一種存儲機制,而非身份認證機制。沒有基於會話的信息可以操作,因為我們沒有會話!

還有一點,token在一段時間以後會過期,這個時候用戶需要重新登錄。這有助於我們保持安全。還有一個概念叫token撤銷,它允許我們根據相同的授權許可使特定的token甚至一組token無效。

5.5. JWT與OAuth的區別

寫在最後:我為大家准備了一些適合於1-5年以上開發經驗的java程序員面試涉及到的絕大部分面試題及答案做成了文檔和學習筆記文件以及架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高並發等架構技術資料),希望可以幫助到大家。

C. web攻擊有哪些怎麼防護

1、DoS和DDoS攻擊(DoS(Denial of Service),即拒絕服務,造成遠程伺服器拒絕服務的行為被稱為DoS攻擊。其目的是使計算機或網路無法提供正常的服務。最常見的DoS攻擊有計算機網路帶寬攻擊和連通性攻擊)
防範:(1) 反欺騙:對數據包的地址及埠的正確性進行驗證,同時進行反向探測。(2) 協議棧行為模式分析:每個數據包類型需要符合RFC規定,這就好像每個數據包都要有完整規范的著裝,只要不符合規范,就自動識別並將其過濾掉。(3) 特定應用防護:非法流量總是有一些特定特徵的,這就好比即便你混進了顧客群中,但你的行為還是會暴露出你的動機,比如老重復問店員同一個問題,老做同樣的動作,這樣你仍然還是會被發現的。(4) 帶寬控制:真實的訪問數據過大時,可以限制其最大輸出的流量,以減少下游網路系統的壓力。
2、CSRF(Cross Site Request Forgery),即跨站請求偽造,是一種常見的Web攻擊,但很多開發者對它很陌生。CSRF也是Web安全中最容易被忽略的一種攻擊。
防範:(1) 驗證碼。應用程序和用戶進行交互過程中,特別是賬戶交易這種核心步驟,強制用戶輸入驗證碼,才能完成最終請求。在通常情況下,驗證碼夠很好地遏制CSRF攻擊。但增加驗證碼降低了用戶的體驗,網站不能給所有的操作都加上驗證碼。所以只能將驗證碼作為一種輔助手段,在關鍵業務點設置驗證碼。(2) Referer Check。HTTP Referer是header的一部分,當瀏覽器向web伺服器發送請求時,一般會帶上Referer信息告訴伺服器是從哪個頁面鏈接過來的,伺服器籍此可以獲得一些信息用於處理。可以通過檢查請求的來源來防禦CSRF攻擊。正常請求的referer具有一定規律,如在提交表單的referer必定是在該頁面發起的請求。所以通過檢查http包頭referer的值是不是這個頁面,來判斷是不是CSRF攻擊。但在某些情況下如從https跳轉到http,瀏覽器處於安全考慮,不會發送referer,伺服器就無法進行check了。若與該網站同域的其他網站有XSS漏洞,那麼攻擊者可以在其他網站注入惡意腳本,受害者進入了此類同域的網址,也會遭受攻擊。出於以上原因,無法完全依賴Referer Check作為防禦CSRF的主要手段。但是可以通過Referer Check來監控CSRF攻擊的發生。(3) Anti CSRF Token。目前比較完善的解決方案是加入Anti-CSRF-Token,即發送請求時在HTTP 請求中以參數的形式加入一個隨機產生的token,並在伺服器建立一個攔截器來驗證這個token。伺服器讀取瀏覽器當前域cookie中這個token值,會進行校驗該請求當中的token和cookie當中的token值是否都存在且相等,才認為這是合法的請求。否則認為這次請求是違法的,拒絕該次服務。這種方法相比Referer檢查要安全很多,token可以在用戶登陸後產生並放於session或cookie中,然後在每次請求時伺服器把token從session或cookie中拿出,與本次請求中的token 進行比對。由於token的存在,攻擊者無法再構造出一個完整的URL實施CSRF攻擊。但在處理多個頁面共存問題時,當某個頁面消耗掉token後,其他頁面的表單保存的還是被消耗掉的那個token,其他頁面的表單提交時會出現token錯誤。
3、XSS(Cross Site Scripting),跨站腳本攻擊。為和層疊樣式表(Cascading Style Sheets,CSS)區分開,跨站腳本在安全領域叫做「XSS」。
防範:(1) 輸入過濾。永遠不要相信用戶的輸入,對用戶輸入的數據做一定的過濾。如輸入的數據是否符合預期的格式,比如日期格式,Email格式,電話號碼格式等等。這樣可以初步對XSS漏洞進行防禦。上面的措施只在web端做了限制,攻擊者通抓包工具如Fiddler還是可以繞過前端輸入的限制,修改請求注入攻擊腳本。因此,後台伺服器需要在接收到用戶輸入的數據後,對特殊危險字元進行過濾或者轉義處理,然後再存儲到資料庫中。(2) 輸出編碼。伺服器端輸出到瀏覽器的數據,可以使用系統的安全函數來進行編碼或轉義來防範XSS攻擊。在PHP中,有htmlentities()和htmlspecialchars()兩個函數可以滿足安全要求。相應的JavaScript的編碼方式可以使用JavascriptEncode。(3) 安全編碼。開發需盡量避免Web客戶端文檔重寫、重定向或其他敏感操作,同時要避免使用客戶端數據,這些操作需盡量在伺服器端使用動態頁面來實現。(4) HttpOnly Cookie。預防XSS攻擊竊取用戶cookie最有效的防禦手段。Web應用程序在設置cookie時,將其屬性設為HttpOnly,就可以避免該網頁的cookie被客戶端惡意JavaScript竊取,保護用戶cookie信息。(5)WAF(Web Application Firewall),Web應用防火牆,主要的功能是防範諸如網頁木馬、XSS以及CSRF等常見的Web漏洞攻擊。由第三方公司開發,在企業環境中深受歡迎。
4、sql注入(SQL Injection),應用程序在向後台資料庫傳遞SQL(Structured Query Language,結構化查詢語言)時,攻擊者將SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字元串,最終達到欺騙伺服器執行惡意的SQL命令。
防範:(1) 防止系統敏感信息泄露。設置php.ini選項display_errors=off,防止php腳本出錯之後,在web頁面輸出敏感信息錯誤,讓攻擊者有機可乘。(2) 數據轉義。設置php.ini選項magic_quotes_gpc=on,它會將提交的變數中所有的』(單引號),」(雙引號),\(反斜杠),空白字元等都在前面自動加上\。或者採用mysql_real_escape()函數或addslashes()函數進行輸入參數的轉義。(3) 增加黑名單或者白名單驗證。白名單驗證一般指,檢查用戶輸入是否是符合預期的類型、長度、數值范圍或者其他格式標准。黑名單驗證是指,若在用戶輸入中,包含明顯的惡意內容則拒絕該條用戶請求。在使用白名單驗證時,一般會配合黑名單驗證。
5、上傳漏洞在DVBBS6.0時代被黑客們利用的最為猖獗,利用上傳漏洞可以直接得到WEBSHELL,危害等級超級高,現在的入侵中上傳漏洞也是常見的漏洞。該漏洞允許用戶上傳任意文件可能會讓攻擊者注入危險內容或惡意代碼,並在伺服器上運行。
防範: (1)檢查伺服器是否判斷了上傳文件類型及後綴。 (2) 定義上傳文件類型白名單,即只允許白名單裡面類型的文件上傳。 (3) 文件上傳目錄禁止執行腳本解析,避免攻擊者進行二次攻擊。 Info漏洞 Info漏洞就是CGI把輸入的參數原樣輸出到頁面,攻擊者通過修改輸入參數而達到欺騙用戶的目的。

D. https+token 能保證絕對安全嗎

不能說絕對安全,但至少是當前最為安全的加密方式,比如說網上銀行的安保級別多高,他們一樣的用的是 https+token 的方式,不過 銀行 都是用的類似 沃通EV SSL證書 這種業界高級別的HTTPS加密證書。

E. url傳輸token的主要危害

會暴露token值。URL攜帶token是不安全的,會暴露token值,token可以放在請求header的Authorization中,在https下傳輸,保證token傳輸的安全,另外token 本身的安全性,演算法是否安全,token應該在服務端生成,密鑰也在服務端,校驗在服務端,這是起碼的安全,另外token也應該有時效性。

F. 鑒權必須了解的 5 個兄弟:cookie、session、token、jwt、單點登錄

本文你將看到:

**「前端存儲」**這就涉及到一發、一存、一帶,發好辦,登陸介面直接返回給前端,存儲就需要前端想辦法了。

前端的存儲方式有很多。

有,cookie。cookie 也是前端存儲的一種,但相比於 localStorage 等其他方式,藉助 HTTP 頭、瀏覽器能力,cookie 可以做到前端無感知。一般過程是這樣的:

「配置:Domain / Path」

cookie 是要限制::「空間范圍」::的,通過 Domain(域)/ Path(路徑)兩級。

「配置:Expires / Max-Age」

cookie 還可以限制::「時間范圍」::,通過 Expires、Max-Age 中的一種。

「配置:Secure / HttpOnly」

cookie 可以限制::「使用方式」::。

**「HTTP 頭對 cookie 的讀寫」**回過頭來,HTTP 是如何寫入和傳遞 cookie 及其配置的呢?HTTP 返回的一個 Set-Cookie 頭用於向瀏覽器寫入「一條(且只能是一條)」cookie,格式為 cookie 鍵值 + 配置鍵值。例如:

那我想一次多 set 幾個 cookie 怎麼辦?多給幾個 Set-Cookie 頭(一次 HTTP 請求中允許重復)

HTTP 請求的 Cookie 頭用於瀏覽器把符合當前「空間、時間、使用方式」配置的所有 cookie 一並發給服務端。因為由瀏覽器做了篩選判斷,就不需要歸還配置內容了,只要發送鍵值就可以。

**「前端對 cookie 的讀寫」**前端可以自己創建 cookie,如果服務端創建的 cookie 沒加HttpOnly,那恭喜你也可以修改他給的 cookie。調用document.cookie可以創建、修改 cookie,和 HTTP 一樣,一次document.cookie能且只能操作一個 cookie。

調用document.cookie也可以讀到 cookie,也和 HTTP 一樣,能讀到所有的非HttpOnly cookie。

現在回想下,你刷卡的時候發生了什麼?

這種操作,在前後端鑒權系統中,叫 session。典型的 session 登陸/驗證流程:

**「Session 的存儲方式」**顯然,服務端只是給 cookie 一個 sessionId,而 session 的具體內容(可能包含用戶信息、session 狀態等),要自己存一下。存儲的方式有幾種:

「Session 的過期和銷毀」**很簡單,只要把存儲的 session 數據銷毀就可以。****「Session 的分布式問題」**通常服務端是集群,而用戶請求過來會走一次負載均衡,不一定打到哪台機器上。那一旦用戶後續介面請求到的機器和他登錄請求的機器不一致,或者登錄請求的機器宕機了,session 不就失效了嗎?這個問題現在有幾種解決方式。

但通常還是採用第一種方式,因為第二種相當於閹割了負載均衡,且仍沒有解決「用戶請求的機器宕機」的問題。**「node.js 下的 session 處理」**前面的圖很清楚了,服務端要實現對 cookie 和 session 的存取,實現起來要做的事還是很多的。在npm中,已經有封裝好的中間件,比如 express-session - npm,用法就不貼了。這是它種的 cookie:

express-session - npm 主要實現了:

session 的維護給服務端造成很大困擾,我們必須找地方存放它,又要考慮分布式的問題,甚至要單獨為了它啟用一套 Redis 集群。有沒有更好的辦法?

回過頭來想想,一個登錄場景,也不必往 session 存太多東西,那為什麼不直接打包到 cookie 中呢?這樣服務端不用存了,每次只要核驗 cookie 帶的「證件」有效性就可以了,也可以攜帶一些輕量的信息。這種方式通常被叫做 token。

token 的流程是這樣的:

**「客戶端 token 的存儲方式」 在前面 cookie 說過,cookie 並不是客戶端存儲憑證的唯一方式。token 因為它的「無狀態性」,有效期、使用限制都包在 token 內容里,對 cookie 的管理能力依賴較小,客戶端存起來就顯得更自由。但 web 應用的主流方式仍是放在 cookie 里,畢竟少操心。 「token 的過期」**那我們如何控制 token 的有效期呢?很簡單,把「過期時間」和數據一起塞進去,驗證時判斷就好。

編碼的方式豐儉由人。**「base64」**比如 node 端的 cookie-session - npm 庫

默認配置下,當我給他一個 userid,他會存成這樣:

這里的 eyJ1c2VyaWQiOiJhIn0=,就是 {"userid":"abb」} 的 base64 而已。 「防篡改」

是的。所以看情況,如果 token 涉及到敏感許可權,就要想辦法避免 token 被篡改。解決方案就是給 token 加簽名,來識別 token 是否被篡改過。例如在 cookie-session - npm 庫中,增加兩項配置:

這樣會多種一個 .sig cookie,裡面的值就是 {"userid":"abb」} 和 iAmSecret通過加密演算法計算出來的,常見的比如HMACSHA256 類 (System.Security.Cryptography) | Microsoft Docs。

好了,現在 cdd 雖然能偽造出eyJ1c2VyaWQiOiJhIn0=,但偽造不出 sig 的內容,因為他不知道 secret。**「JWT」**但上面的做法額外增加了 cookie 數量,數據本身也沒有規范的格式,所以 JSON Web Token Introction - jwt.io 橫空出世了。

它是一種成熟的 token 字元串生成方案,包含了我們前面提到的數據、簽名。不如直接看一下一個 JWT token 長什麼樣:

這串東西是怎麼生成的呢?看圖:

類型、加密演算法的選項,以及 JWT 標准數據欄位,可以參考 RFC 7519 - JSON Web Token (JWT)node 上同樣有相關的庫實現:express-jwt - npm koa-jwt - npm

token,作為許可權守護者,最重要的就是「安全」。業務介面用來鑒權的 token,我們稱之為 access token。越是許可權敏感的業務,我們越希望 access token 有效期足夠短,以避免被盜用。但過短的有效期會造成 access token 經常過期,過期後怎麼辦呢?一種辦法是,讓用戶重新登錄獲取新 token,顯然不夠友好,要知道有的 access token 過期時間可能只有幾分鍾。另外一種辦法是,再來一個 token,一個專門生成 access token 的 token,我們稱為 refresh token。

有了 refresh token 後,幾種情況的請求流程變成這樣:

如果 refresh token 也過期了,就只能重新登錄了。

session 和 token 都是邊界很模糊的概念,就像前面說的,refresh token 也可能以 session 的形式組織維護。狹義上,我們通常認為 session 是「種在 cookie 上、數據存在服務端」的認證方案,token 是「客戶端存哪都行、數據存在 token 里」的認證方案。對 session 和 token 的對比本質上是「客戶端存 cookie / 存別地兒」、「服務端存數據 / 不存數據」的對比。**「客戶端存 cookie / 存別地兒」**存 cookie 固然方便不操心,但問題也很明顯:

存別的地方,可以解決沒有 cookie 的場景;通過參數等方式手動帶,可以避免 CSRF 攻擊。 「服務端存數據 / 不存數據」

前面我們已經知道了,在同域下的客戶端/服務端認證系統中,通過客戶端攜帶憑證,維持一段時間內的登錄狀態。但當我們業務線越來越多,就會有更多業務系統分散到不同域名下,就需要「一次登錄,全線通用」的能力,叫做「單點登錄」。

簡單的,如果業務系統都在同一主域名下,比如wenku..com tieba..com,就好辦了。可以直接把 cookie domain 設置為主域名 .com,網路也就是這么乾的。

比如滴滴這么潮的公司,同時擁有didichuxing.com xiaojukeji.com didiglobal.com等域名,種 cookie 是完全繞不開的。這要能實現「一次登錄,全線通用」,才是真正的單點登錄。這種場景下,我們需要獨立的認證服務,通常被稱為 SSO。 「一次「從 A 系統引發登錄,到 B 系統不用登錄」的完整流程」

**「完整版本:考慮瀏覽器的場景」**上面的過程看起來沒問題,實際上很多 APP 等端上這樣就夠了。但在瀏覽器下不見得好用。看這里:

對瀏覽器來說,SSO 域下返回的數據要怎麼存,才能在訪問 A 的時候帶上?瀏覽器對跨域有嚴格限制,cookie、localStorage 等方式都是有域限制的。這就需要也只能由 A 提供 A 域下存儲憑證的能力。一般我們是這么做的:

圖中我們通過顏色把瀏覽器當前所處的域名標記出來。注意圖中灰底文字說明部分的變化。

謝謝大家哦

G. 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 劫持)—— 瀏覽器安全」

H. Spring Security 整合 JSON Web Token(JWT)

註:參考 Spring Security 整合 JSON Web Token(JWT) 提升 REST 安全性 ,寫的特別全面,本文只是學習總結

基於token的鑒權機制

基於token的鑒權機制類似於http協議也是無狀態的,它不需要在服務端去保留用戶的認證信息或者會話信息。這就意味著基於token認證機制的應用不需要去考慮用戶在哪一台伺服器登錄了,這就為應用的擴展提供了便利。

流程上是這樣的:

1.用戶使用用戶名密碼來請求伺服器

2.伺服器進行驗證用戶的信息

3.伺服器通過驗證發送給用戶一個token

4.客戶端存儲token,並在每次請求時附送上這個token值

5.服務端驗證token值,並返回數據

這個token必須要在每次請求時傳遞給服務端,它應該保存在請求頭里, 另外,服務端要支持CORS(跨來源資源共享)策略,一般我們在服務端這么做就可以了Access-Control-Allow-Origin: *。

第一部分我們稱它為頭部(header),第二部分我們稱其為載荷(payload, 類似於飛機上承載的物品),第三部分是簽證(signature).

jwt的頭部承載兩部分信息:

聲明類型,這里是jwt

聲明加密的演算法 通常直接使用 HMAC SHA256

完整的頭部就像下面這樣的JSON:

然後將頭部進行base64加密(該加密是可以對稱解密的),構成了第一部分.

載荷就是存放有效信息的地方。這個名字像是特指飛機上承載的貨品,這些有效信息包含三個部分

1.標准中注冊的聲明

2.公共的聲明

3.私有的聲明

標准中注冊的聲明 (建議但不強制使用) :

iss : jwt簽發者

sub : jwt所面向的用戶

aud : 接收jwt的一方

exp : jwt的過期時間,這個過期時間必須要大於簽發時間

nbf : 定義在什麼時間之前,該jwt都是不可用的.

iat : jwt的簽發時間

jti : jwt的唯一身份標識,主要用來作為一次性token,從而迴避重放攻擊。

公共的聲明 :

公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密.

私有的聲明 :

私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味著該部分信息可以歸類為明文信息。

定義一個payload:

然後將其進行base64加密,得到Jwt的第二部分。

jwt的第三部分是一個簽證信息,這個簽證信息由三部分組成:

1.header (base64後的)

2.payload (base64後的)

3.secret

這個部分需要base64加密後的header和base64加密後的payload使用.連接組成的字元串,然後通過header中聲明的加密方式進行加鹽secret組合加密,然後就構成了jwt的第三部分。

將這三部分用.連接成一個完整的字元串,構成了最終的jwt:

注意:secret是保存在伺服器端的,jwt的簽發生成也是在伺服器端的,secret就是用來進行jwt的簽發和jwt的驗證,所以,它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發jwt了。

如何應用

一般是在請求頭里加入Authorization,並加上Bearer標註:

服務端會驗證token,如果驗證通過就會返回相應的資源。整個流程就是這樣的:

jwt-diagram

總結

優點

因為json的通用性,所以JWT是可以進行跨語言支持的,像JAVA,JavaScript,NodeJS,PHP等很多語言都可以使用。

因為有了payload部分,所以JWT可以在自身存儲一些其他業務邏輯所必要的非敏感信息。

便於傳輸,jwt的構成非常簡單,位元組佔用很小,所以它是非常便於傳輸的。

它不需要在服務端保存會話信息, 所以它易於應用的擴展

安全相關

不應該在jwt的payload部分存放敏感信息,因為該部分是客戶端可解密的部分。

保護好secret私鑰,該私鑰非常重要。

如果可以,請使用https協議

在SpringBoot中整合JWTSpring Security的步奏:

1.在項目中引入(本項目使用Gradle)

2.配置

目錄結構如下:

WebSecurityConfig文件: