有篇關於JWT的文章,叫「JWT: The Complete Guide to JSON Web Tokens」,寫得全面細緻。爲了本身能更清晰理解並惠及更多人,我把它大體翻譯了過來,有些地方稍顯冗餘就去掉了,但仍是接近八千字,感謝原做者!如下是正文:javascript
本文的目標是讓你學習JWT的工做原理和細節,以及它在Web應用中能如何幫助你實現用戶認證和會話管理功能。那爲何須要深刻理解JWT呢?由於這樣有助於你:java
即便選擇了某個基於JWT的認證方案,一樣還須要進行代碼編寫,編碼工做主要是在客戶端,但服務端也須要一些。node
到本文的結尾,你將深入理解JWT,包括它基於的加密技術,這種加密技術也普遍使用在其餘安全案例中。你還將明白何時該用JWT和爲何要使用,同時理解JWT的數據格式,可使用各類線上工具去分析解決簽名上遇到的問題。算法
爲何是JWT?shell
相比在內存中存儲隨機token的用戶會話管理方式來講,JWT最大的優點是,它使得將認證邏輯委託給第三方服務成爲可能,這些服務包括:數據庫
外部認證服務能夠徹底獨立於咱們本身的應用服務,而且不須要經過網絡共享任何密鑰信息。應用服務器不須要安裝任何密鑰,減小了密鑰丟失或者被盜竊的風險。小程序
此外,應用服務能夠徹底無狀態,由於不須要在多個請求之間將token存儲在內存。認證服務能夠在生成token並返回給客戶端後,立刻丟棄它!一樣,密碼摘要也沒有必要保存在應用數據庫中,所以減小了被盜的風險和其它安全相關的bug。瀏覽器
此刻也許你內心想:我有一個內部應用,對此,JWT是一個好的方案嗎?是的,在本文的最後一節裏,咱們將討論JWT在這種典型場景下的使用狀況。安全
本文咱們將討論如下這些話題:bash
JSON Web Token (or JWT)只是一個包含某種意義數據的JSON串。它最重要的特性就是,爲了確認它是否有效,咱們只須要看JWT自己的內容,而不須要藉助於第三方服務或者在多個請求之間將其保存在內存中-這是由於它自己攜帶了信息驗證碼MAC(Message Authentication Code)。
一個JWT包含3個部分:頭部Header,數據Payload,簽名Signature。讓咱們逐個來了解一下,先從Payload開始吧。
Payload只是一個普通的Javascript 對象。對於payload的內容,JWT是沒有任何限制的,但必須注意的是,JWT是沒有加密的。所以,任何放在token裏面的信息,若是被截獲了,對任何人別人是可讀的。所以,咱們不該該在Payload裏面存聽任何黑客能夠利用的用戶信息。
Payload的內容在接收者端是經過簽名(Signature)來校驗的。不過存在多種類型的簽名,所以,接收者須要知道使用的是哪一種類型的簽名。
這種關於token自己的元數據信息存放在另外的Javascript對象裏面,並隨着Payload一塊兒發送給客戶。這個獨立的對象就是一個JSON對象,叫JWT Header,它也是普通的Javascript對象,在這裏面咱們能夠看到簽名類型信息,好比RS256。
JWT的最後一部分是簽名,它也叫信息驗證碼MAC。簽名只能由擁有Payload、Header和密鑰的角色生成。
那簽名是如何完成認證功能的呢,且看:
這樣的話,黑客假扮合法用戶的辦法要麼是盜到了用戶名和密碼組合,要麼盜到了認證服務器上的簽名私鑰。
正如咱們所見,簽名的確是JWT的關鍵部分!
簽名使得無狀態的服務器只須要經過查看HTTP請求中的JWT token就能保證HTTP請求是來自某個用戶,而不須要每次請求時都發送密碼。
實際上,JWT真正的好處是讓認證服務器和校驗JWT token的應用服務器能夠徹底分開,而讓服務器無狀態化只是它的一個反作用罷了。這意味着應用服務器只須要最簡單的認證邏輯-校驗JWT!咱們能夠將整個應用集羣的登陸/註冊委託給一個單獨的認證服務器。這也意味着應用服務器更簡單更安全,由於更多的認證功能集中部署在認證服務器,能夠被跨應用使用。
到此,咱們從更高的層面瞭解了JWT是怎樣完成無狀態的第三方認證,接下來讓咱們瞭解它的實現細節。
讓咱們來看看JWT的實際例子,這是從jwt.io的JWT校驗工具獲得的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
你可能會想,JSON對象去哪了啊?不過,你會立刻找回它。
咱們能夠看到,這個JWT包含3部分,是由「.」號分開的。第一部分是JWT的Header:
JWT Header:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
第二部分是Payload:
JWT Payload:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
第三方部分是簽名Signature:
JWT Signature:
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
若是你還想確認這些信息是否真的存在,能夠拷貝JWT串到jwt.io的在線校驗工具校驗一下便可。
但這些字符串表明什麼意思呢?咱們如何取回JWT的信息?
無論你信不信,如今的Payload,Header和Signature仍是可讀的。這只是由於咱們不想在網絡傳輸過程當中出現一些垃圾文本,好比這樣的字符串:qîüö:Ã。
這是由於世界上不一樣的計算機以不一樣的編碼方式處理字符串,好比UTF-8,ISO 8859-1,等等。所以,這種問題處處存在,只要咱們在某個平臺上用到一個字符串,它老是使用了某種編碼方式,即便咱們沒有顯示指定:
咱們但願在網絡上傳輸字符串時沒有這些問題,那就須要選擇這些字符的一個子集,對於這個子集,幾乎全部的編碼方式都是同樣的處理方式,這就是Base64編碼方式產生的緣由。
可是咱們在JWT看到的並非Base64,其實是Base64Url,它和Base64相似,但有一些字符不同,所以咱們能夠將JWT做爲URL的參數進行傳遞。
咱們看一下Payload部分:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
咱們使用在線解碼器來解析它,就獲得了一個JSON對象,所以,咱們能夠獲得這樣的結論:JWT Header和Payload的內容是普通的javascript對象,轉換成JSON並進行Base64Url編碼,以「.」號隔開。
在學習簽名Signature以前,咱們先來看看在實際的用戶認證案例中,咱們是將哪些內容放入Payload中的。
以前有提到,JWT的Payload理論上能夠存聽任何內容,不必定是用戶身份信息,只不過使用JWT做爲認證是最經常使用的方式。Payload還有一些特定的屬性來支持:
這裏是Payload的幾個最經常使用的標準屬性:
· iss 表明生成token的實體,通常就是認證服務器
· iat 建立JWT的時間戳(in seconds since Epoch)
· sub 包含用戶的身份信息
· exp token的過時時間戳
咱們把這叫作Bearer Token,意思是:
認證服務器確認這個token的持有者是具備由sub屬性表示的ID的用戶,所以能夠放行。
如今咱們理解了Payload在用戶認證中是如何使用的,接下來咱們來了解一下簽名Signature。對於JWT,簽名方式有不少種,這裏咱們主要了解HS256和RS256。
咱們先來看看HS256.
和不少簽名方法同樣,HS256 數字簽名基於一種特殊的函數:加密哈希函數。
這聽起來有點唬人,不過是個值得學習的概念:這個知識已經被使用了20多年並還會持續很長時間。不少關於安全的實現都圍繞着哈希,它在Web安全中隨處可見。
咱們將分爲兩步,首先要了解什麼是哈希函數,而後再看經過這樣的函數和密碼,如何生成信息認證碼(Message Authentication Code),也就是數字簽名。
哈希函數是一種特殊的函數:它在數字簽名中有不少實際的使用案例。如今咱們將談論它四個有趣的屬性,而後看看這些屬性如何使得咱們能夠生成可校驗的簽名。這裏咱們將使用的哈希函數是:SHA-256。
哈希函數有點相似絞肉機:你把牛排放入一端,而後從另外一端獲得漢堡包,你再也沒法從漢堡包取回牛排了。所以,函數是徹底不可逆的。這就意味着咱們把Header和Payload做用於這個函數後,沒有人能夠從函數輸出的信息中取回Header和Payload的原始值。
使用在線的哈希計算器,咱們能夠看到SHA-256的一個輸出值以下:
3f306b76e92c8a8fbae88a3ef1c0f9b0a81fe3a953fa9320d5d0281b059887c3
同時,哈希並非加密,加密在定義中是可逆的,咱們老是須要從加密後的信息中獲得原始信息。
另一個須要知道的是,哈希函數是可重複生成信息的,也就是若是咱們輸入一樣的Header和Payload信息,每次獲得的結果是徹底同樣的。這就意味着,給定輸入組合和哈希輸出值,咱們老是能夠校驗該輸出值(好比簽名signature)的正確性,由於咱們能夠從新計算(咱們有輸入值的狀況下)。
還有一個屬性是,若是咱們提供不一樣的輸入值,老是獲得不一樣的惟一的輸出值。這就意味着咱們將哈希函數做用於某個Payload和Header以後,老是獲得相同的結果,其它輸入值組合不會獲得和這同樣的結果,所以,哈希函數的不一樣輸出值就表明了輸入值的不一樣。
哈希函數的最後一個屬性就是不可預測性,給定一個輸出值,沒法經過各類手段猜想到輸入值。假設咱們嘗試從上面的輸出值中找到生成它的Payload,咱們只能猜想輸入值而後對比輸出值看看是否匹配。
但對於哈希函數來講,這種方式是不可行的:
這是由於在哈希函數中,即便你改變了一個輸入字符甚至一個比特值,輸出中通常有50%的比特值都會被改變,輸入值小小的變更,可能會獲得徹底不一樣的輸出值。
這些聽起來挺有趣的,不過你可能又在想了:哈希函數是怎樣完成數字簽名的呢?黑客是否能夠拿着Header和Payload,而無論Signature呢?任何人均可以使用SHA-256哈希函數生成一個輸出,而後附加到JWT的signature部分,對吧?
這是正確的,任何人均可以使用哈希函數,而後輸入Header和Payload來生成結果。但HS256簽名不止這樣,咱們拿到Header、Payload外,還要加上一個密碼,將這三個輸入值一塊兒哈希。輸出結果是一個SHA-256 HMAC或者基於哈希的MAC。若是須要重複生成,則須要同時擁有Header、Payload和密碼才能夠。這也意味着,哈希函數的輸出結果是一個數字簽名,由於輸出結果就表示了Payload是由擁有密碼的角色生成並加簽了的,沒有其它方式能夠生成這樣的輸出值了。
將哈希結果附加到消息上,是爲了讓接收者能夠驗證。哈希結果叫HMAC:Hash-Based Message Authentication Code,是數字簽名的一種形式。這就是咱們在JWT中所作的,JWT的第三部分是由Header、Payload經過SHA-256函數生成,並使用Base64Url進行編碼。
當咱們的服務接收到HS256簽名的JWT時,咱們須要使用一樣的密碼才能校驗並確認token裏面的Payload是否有效。爲了驗證簽名,咱們只須要將JWT Header和Payload以及密碼經過哈希函數生成結果。若是是使用HS256函數,JWT的接收者須要拿到和發送者同樣的密碼值。若是咱們獲得的哈希結果和JWT第三部分的簽名值是一致的,則說明有效,能夠確認發送者確實和接收者擁有相同的密碼值。
而數字簽名和HMAC又是如何工做的呢?
咱們從以前的JWT中去掉簽名和第二個「.」,只留下Header和Payload部分。看起來以下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
如今若是你拷貝這個字符串到在線的HMAC SHA-256工具,並使用上密碼,就能夠取回JWT簽名。或者,你會獲得Base64編碼後的內容,後面還有一個「=」字符,這算是已經接近Base64Url:
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ=
那個「=」在URL欄中會顯示爲「%3D」,會顯得混亂,這也解釋了在咱們把JWT拼接到URL發送時,須要Base64Url的緣由。
以上解釋了JWT簽名是如何應用於認證的,HS256只是一種具體的簽名類型。其它的簽名類型中,最經常使用的是:RS256。
有什麼區別呢?咱們介紹HS256只是爲了更容易理解MAC碼的概念, 你可能也會發現它在一些生產環境的應用中被使用。可是通常來講,使用RS256簽名方式會更好,下一節咱們將看到,RS256相對於HS256來講有諸多優點。
若是輸入的密碼相對弱的話,HS256可能會被暴力破解,基於密鑰的技術都有這個問題。更甚的是,HS256要求JWT的生產者和消費者都預先擁有相同的密碼。
這意味着咱們在修改密碼後,須要把它分發並安裝到全部須要它的網絡節點。這不只不方便,並且容易出錯,還涉及到服務器間的協調和暫停服務問題。若是服務器是由另外的團隊維護,好比第三方組織,這種方式就更不可行了。
建立和校驗JWT的能力沒有區分開,使用HS256時,網絡的任何人均可以建立和校驗token,由於他們都有密碼。這就意味着密碼可能會從更多的地方丟失或者受攻擊,由於密碼處處分發,而並非每一個應用都具備同樣的安全保護機制。
彌補這問題的一個方法是,建立一個共享的密碼給每一種類型的應用。不過,咱們立刻要學習新的簽名方式,這個簽名方式解決了以上全部的問題,而且目前全部基於JWT的方案都默認使用的,那就是RS256。
使用RS256咱們一樣須要生成一個MAC,其目的仍然是建立一個數字簽名來證實一個JWT的有效性。只是在這種簽名方式中就,咱們將建立token和校驗token的能力分開,只有認證服務器具有建立的能力,而應用服務器,具有校驗的能力。
這樣,咱們須要建立兩個密鑰而不是一個:
RS256使用一種特殊的密鑰,叫RSA密鑰。RSA是一種加解密算法,使用一個密鑰進行加密,而後用另一個密鑰解密。值得注意的是,RSA不是哈希函數,從定義上來講,這種方式加密是可逆的,也就是咱們能夠從加密後的內容獲得原始內容。
來看一下RSA公鑰是怎樣的:
—–BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
—–END PUBLIC KEY—–
乍一看有點古怪,但它是使用命令行工具好比openssl 或者在線的RSA密鑰生成工具來生成的。
這個公鑰是公開發布的,所以黑客根本不須要猜想,他原本就能夠擁有它。
但這裏還有一個RSA私鑰:
—–BEGIN RSA PRIVATE KEY—–
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQABAoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5CpuGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0KSu5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aPFaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
—–END RSA PRIVATE KEY—–
好消息是,黑客沒有任何辦法猜想私鑰。
並且,這兩個密鑰是相關的,一個密鑰加密的內容只能由另外的密鑰來解密。那咱們又如何用它們生成簽名呢?
如今嘗試着使用RSA來生成一個數字簽名:
咱們使用Header和Payload,而後使用私鑰對其進行RSA加密,最後返回JWT。
接收者拿到JWT後,使用公鑰解密,而後檢查解密後的值。若是解密過程順利而且其輸出是一個JSON值,每每就意味着該JWT就是認證服務器建立並加密了的。
相比哈希函數,RSA加密過程比較慢。對於數據比較大的Payload來講,可能會是個問題。
那HS256簽名方式在實際中又是如何使用RSA的呢?
在實際中,咱們通常先將Header和Payload一塊兒哈希,好比使用SHA-256。這個速度是很快的,這樣咱們就獲得了一個表明輸入數據的惟一表示,比實際輸入數據要小得多。
而後咱們使用RSA對哈希結果而不是完整的數據(Header+Payload)進行加密,就獲得了RS256簽名。咱們將這個簽名附加到JWT的第三部分,而後返回給客戶端。
接收者將:
任何人均可以計算哈希值,但只有認證服務器可使用RSA私鑰對其進行加密。
接下來咱們學習一下在RS256簽名中遇到問題時的解決思路。
咱們看下jwt.io上的例子,一個使用RS256加簽的JWT。
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
從表面上看,這和HS256 JWT沒有多大區別,但這是使用前面展現的同一個RSA私鑰加簽了的。
咱們把簽名部分去掉,只看Header和Payload:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
如今咱們須要作的就是使用SHA-256對其進行哈希,而後使用上面的RSA私鑰進行加密。這樣獲得的結果就是JWT簽名,咱們可使用Node的內嵌模塊Crypto來確認。
首先,咱們把RSA私鑰保存到一個文本文件,好比叫private.key。而後在命令行運行node shell,執行一個小程序,獲得下面的結果:
EkN+DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W/A4K8ZPJijNLis4EZsHeY559a4DFOd50/OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k/4zM3O+vtd1Ghyo4IbqKKSy6J9mTniYJPenn5+HIirE=
這個結果和JWT簽名徹底不一樣,不過等等,這裏面還有斜槓和等號。若是不進一步處理,這是無法放到URL裏面的。
這是由於咱們生成的是Base64 版本的簽名,而咱們真正須要的是Base64Url 版本的。咱們嘗試轉換一下:
bash$ node
const base64url = require(‘base64url’);
base64url.fromBase64("EkN+DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W/A4K8ZPJijNLis4EZsHeY559a4DFOd50/OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k/4zM3O+vtd1Ghyo4IbqKKSy6J9mTniYJPenn5+HIirE=");
獲得下面的結果:
EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE
這就是咱們真正想要建立的RS256簽名了!也證實了咱們對RS256 JWT簽名的理解是正確的,並且咱們知道了在遇到問題時如何去分析解決。
總之,RS256 JWT簽名就是使用RSA對Header和Payload的哈希值進行加密的結果。如今咱們知道RS256簽名是如何工做的了,但這些簽名爲何好於HS256簽名呢?
使用RS256,黑客能夠輕鬆實現建立簽名的第一步,即根據盜來的JWT Header和Payload生成SHA-256哈希值,以後他還要暴力破解RSA才能繼續生成簽名。
但這還不是咱們爲何選擇RS256而不是HS256的客觀緣由。
咱們知道,使用RS256時,私鑰只有認證服務器持有,這就安全得多- 加簽密鑰丟失的風險下降了。然而選擇RS256更重要的理由是-簡化密鑰分發。
還記得以前咱們說過,用來校驗token的公鑰能夠隨意分發,黑客沒法使用它來作任何有意義的事情。然而黑客並非想校驗token,他們只是想僞造它們。這就使得咱們將公鑰放置到受咱們本身控制的服務器上成爲可能。
應用服務器鏈接到公鑰放置的服務器獲取公鑰,而後按期檢查公鑰是否有變化。所以,在更新密鑰時,應用服務器和認證服務器不須要同時暫停服務。
那公鑰又如何分發呢?下面是一種可行的格式。
有多種發佈公鑰的格式,但這裏有一種較爲熟悉:JWKS,全稱Json Web Key Set。
若是你好奇這些endpoints 看起來是怎樣的,能夠看一下這個線上例子live example,下面這個是咱們從HTT GET請求獲得的回覆:
Kid是密鑰身份, x5c是某種公鑰的表示法。這種格式的優勢是其標準化,咱們只須要知道endpoint的URL,和一個能夠解析JWKS的庫,就可使用公鑰來校驗JWT了,而不須要安裝到本身的服務器。
JWT經常使用在公共網站上,以及社交產品的登陸方案中。對於內部系統,它是怎麼被使用的呢?
JWT一樣適用於企業內部,替代經典的存在已知安全隱患的預身份驗證設置(Pre-Authentication setup)方式。
預身份驗證設置方式中,咱們的應用服務器在私有網絡的一個代理後面運行,而後從HTTP請求頭中獲取當前用戶信息。表明用戶身份的HTTP請求頭一般由中心化的登陸頁面填充,同時中心化的節點也對用戶session進行管理。
當session過時後,服務器將阻止對應用的訪問,並要求用戶從新登陸認證。以後,它將全部請求轉發到應用服務器並在HTTP請求頭添加表明用戶身份的信息。
問題是這種設置方式,內網上的任何人均可以假扮成某個用戶,只要設置一樣的HTTP請求頭。
對此也有一些解決方案,好比白名單列表,或者某種客戶憑證。
預身份驗證設置方式是一個好主意,畢竟這種方式可使得應用開發者不須要實現認證邏輯,減小開發時間和潛在的安全問題。
若是能有預身份驗證設置方式的便捷,又沒有安全方面的妥協,豈不美哉?
若是咱們考慮到JWT,則能夠輕鬆作到。咱們不像以往那樣將用戶名放到HTTP請求頭,而是將HTTP請求頭封裝成一個JWT。咱們將用戶名放到Payload裏面,再由認證服務器加簽。
應用服務器再也不從HTTP請求頭獲取用戶名,而是首先校驗JWT:
這樣的結果就是,即便在私有網絡內,咱們的認證功能也能夠正常工做。咱們不再須要經過HTTP請求頭來識別用戶了,咱們保證了HTTP請求頭的有效性而且是由代理生成的,而不是某黑客試圖以某個用戶身份登陸。
經過本文,咱們對JWT是什麼有了一個全面的瞭解,以及它是如何在認證中被使用的。JWT只是一個簡單的JSON對象,而且易於驗證、難於僞造。
此外,JWT並非必定要用來作認證的,咱們可使用JWT在網絡上發送各類數據。
另一個和安全相關的使用JWT的狀況是受權:咱們能夠在Payload裏面放置用戶的角色列表,好比只讀用戶、管理員等等,對用戶在應用服務器上的行爲進行限制。
好了,本文到此結束,祝你閱讀愉快!
文章來源:想全面理解JWT?一文足矣!