ASP.NET Core 基于JWT的認(rèn)證(一)

導(dǎo)讀

Json web token (JWT), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)((RFC 7519).該token被設(shè)計(jì)為緊湊且安全的,特別適用于分布式站點(diǎn)的單點(diǎn)登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該token也可直接被用于認(rèn)證,也可被加密。

我們知道,http協(xié)議本身是一種無狀態(tài)的協(xié)議,而這就意味著如果用戶向我們的應(yīng)用提供了用戶名和密碼來進(jìn)行用戶認(rèn)證,那么下一次請(qǐng)求時(shí),用戶還要再一次進(jìn)行用戶認(rèn)證才行,因?yàn)楦鶕?jù)http協(xié)議,我們并不能知道是哪個(gè)用戶發(fā)出的請(qǐng)求,所以為了讓我們的應(yīng)用能識(shí)別是哪個(gè)用戶發(fā)出的請(qǐng)求,我們只能在服務(wù)器存儲(chǔ)一份用戶登錄的信息,這份登錄信息會(huì)在響應(yīng)時(shí)傳遞給瀏覽器,告訴其保存為cookie,以便下次請(qǐng)求時(shí)發(fā)送給我們的應(yīng)用,這樣我們的應(yīng)用就能識(shí)別請(qǐng)求來自哪個(gè)用戶了。

幾種常見的傳統(tǒng)認(rèn)證機(jī)制

HTTP Basic Auth

HTTP Basic Auth簡單點(diǎn)說明就是每次請(qǐng)求API時(shí)都提供用戶的usernamepassword,簡言之,Basic Auth是配合RESTful API 使用的最簡單的認(rèn)證方式,只需提供用戶名密碼即可,但由于有把用戶名密碼暴露給第三方客戶端的風(fēng)險(xiǎn),在生產(chǎn)環(huán)境下被使用的越來越少。因此,在開發(fā)對(duì)外開放的RESTful API時(shí),盡量避免采用HTTP Basic Auth。

OAuth

OAuth(開放授權(quán))是一個(gè)開放的授權(quán)標(biāo)準(zhǔn),允許用戶讓第三方應(yīng)用訪問該用戶在某一web服務(wù)上存儲(chǔ)的私密的資源(如照片,視頻,聯(lián)系人列表),而無需將用戶名和密碼提供給第三方應(yīng)用。

OAuth允許用戶提供一個(gè)令牌,而不是用戶名和密碼來訪問他們存放在特定服務(wù)提供者的數(shù)據(jù)。每一個(gè)令牌授權(quán)一個(gè)特定的第三方系統(tǒng)(例如,視頻編輯網(wǎng)站)在特定的時(shí)段(例如,接下來的2小時(shí)內(nèi))內(nèi)訪問特定的資源(例如僅僅是某一相冊(cè)中的視頻)。這樣,OAuth讓用戶可以授權(quán)第三方網(wǎng)站訪問他們存儲(chǔ)在另外服務(wù)提供者的某些特定信息,而非所有內(nèi)容
下面是OAuth2.0的流程:

image

Cookie Auth

Cookie認(rèn)證機(jī)制就是為一次請(qǐng)求認(rèn)證在服務(wù)端創(chuàng)建一個(gè)Session對(duì)象,同時(shí)在客戶端的瀏覽器端創(chuàng)建了一個(gè)Cookie對(duì)象;通過客戶端帶上來Cookie對(duì)象來與服務(wù)器端的session對(duì)象匹配來實(shí)現(xiàn)狀態(tài)管理的。默認(rèn)的,當(dāng)我們關(guān)閉瀏覽器的時(shí)候,cookie會(huì)被刪除。但可以通過修改Cookieexpire time使cookie在一定時(shí)間內(nèi)有效;

兩種對(duì)比

Token 簡介

JWT (Json Web Token)是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)。

JWT的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源。比如用在用戶登錄上。

有些朋友可能會(huì)認(rèn)為,我登錄只需要用緩存或者數(shù)據(jù)庫記錄下一個(gè)特征碼或者是Cookies就可以了,為什么要使用JWT呢?我們知道一個(gè)數(shù)據(jù)庫或者是一個(gè)軟件,損耗時(shí)間最大的地方就是我們的 I/O(輸入輸出,通常指的就是硬盤的讀寫),因此我們選擇解碼一次HS256,對(duì)于現(xiàn)在的計(jì)算能力強(qiáng)大的計(jì)算機(jī)而言,解一次HS256比訪問一次磁盤要快得多。

基于token的鑒權(quán)機(jī)制類似于http協(xié)議也是無狀態(tài)的,它不需要在服務(wù)端去保留用戶的認(rèn)證信息或者會(huì)話信息。這就意味著基于token認(rèn)證機(jī)制的應(yīng)用不需要去考慮用戶在哪一臺(tái)服務(wù)器登錄了,這就為應(yīng)用的擴(kuò)展提供了便利。
流程上是這樣的:


image
  • 用戶使用用戶名密碼來請(qǐng)求服務(wù)器
  • 服務(wù)器進(jìn)行驗(yàn)證用戶的信息
  • 服務(wù)器通過驗(yàn)證發(fā)送給用戶一個(gè)token
  • 客戶端存儲(chǔ)token,并在每次請(qǐng)求時(shí)附送上這個(gè)token值
  • 服務(wù)端驗(yàn)證token值,并返回?cái)?shù)據(jù)

這個(gè)token必須要在每次請(qǐng)求時(shí)傳遞給服務(wù)端,它應(yīng)該保存在請(qǐng)求頭里, 另外,服務(wù)端要支持CORS(跨來源資源共享)策略,一般我們?cè)诜?wù)端這么做就可以了Access-Control-Allow-Origin: *。
那么我們現(xiàn)在回到JWT的主題上。

JWT 的組成

我們先來看一段jwt

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

仔細(xì)觀察我們可以發(fā)現(xiàn)這一段字符串中含有兩個(gè) " . ",這兩個(gè) " . "jwt分成了三份,我們分別成為頭部、荷載信息、簽證信息。那么這三部分的分工是什么呢?

Header

JWT的頭部承載了兩個(gè)信息

  • 聲明類型,對(duì)于Jwt來說就是jwt
  • 加密算法,通常使用SHA256,HS256

完整的頭部應(yīng)該是像這樣的一個(gè)Json

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

將頭部Json進(jìn)行base64加密就得到了我們的第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

Payload

第二部分是荷載信息,Payload,你可以理解為我們的JWT是一輛大倉庫,第一部分頭部就是倉庫的名稱編號(hào)等基礎(chǔ)信息,而荷載信息就是倉庫的本身,包含了倉庫里面的所有貨物。這些信息又包含了三個(gè)部分:

  • 標(biāo)準(zhǔn)中注冊(cè)的聲明
  • 公共的聲明
  • 私有的聲明

標(biāo)準(zhǔn)中注冊(cè)的聲明 (建議但不強(qiáng)制使用)

  • iss: jwt簽發(fā)者

  • sub: jwt所面向的用戶

  • aud: 接收jwt的一方

  • exp: jwt的過期時(shí)間,這個(gè)過期時(shí)間必須要大于簽發(fā)時(shí)間

  • nbf: 定義在什么時(shí)間之前,該jwt都是不可用的.

  • iat: jwt的簽發(fā)時(shí)間

  • jti: jwt的唯一身份標(biāo)識(shí),主要用來作為一次性token,從而回避重放攻擊。

公共的聲明 :

公共的聲明可以添加任何的信息,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要息。但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷堋?/p>

私有的聲明 :

私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對(duì)稱解密的,意味著該部分信息可以歸類為明文信息。

事實(shí)上我們的Header和Payload都是基于base64加密的,這種密文都是可以對(duì)稱解密的,因此請(qǐng)不要存放敏感信息。

定義一個(gè)payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

進(jìn)行base64加密后,得到了我們的第二部分

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

Signature

Jwt的第三部分是一個(gè)簽證信息,這個(gè)簽證信息由三部分組成:

  • header (base64后的)
  • payload (base64后的)
  • secret

這一部分可以理解為對(duì)前部分的一個(gè)校驗(yàn),將前兩部分加密后的密文通過在Header中定義的加密方式,與服務(wù)端所傳入的密鑰進(jìn)行一次加密,假如前兩部分的信息被篡改的話,必然通不過最后一部分簽證的校驗(yàn)。因此通過這樣保證了Jwt的安全性。

因此,保存并隱藏好我們的加密密鑰是非常重要的,假設(shè)泄露了,就意味著任何知道密鑰的人都可以輕松的對(duì)jwt進(jìn)行自我簽發(fā)和驗(yàn)證。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容