開發隨筆記錄——關於JWT(身份令牌效驗)的有關內容。
宣告:本次記錄僅供參考,若設計到利益等問題,請聯絡博主進行刪帖。
接下來,開始我的獨白。博主在開發過程中也是遇到了很多關於JWT的問題,也是參考了很多前輩的經驗也參考了官網的說明文件,要是有什麼理解不對的地方還請各路大神指點一二。好了,我們步入主題。
以下內容皆是在官網copy下來,不想看這些囉嗦話的同志可以直接看主體內容。
什麼是 JWT?
所謂的JWT也就是叫做JSON Web Token。那麼JSON Web Token (JWT) 是一個開放標準 (RFC 7519),它定義了一種緊湊且自包含的方式,用於在各方之間作為 JSON 物件安全地傳輸資訊。該資訊可以被驗證和信任,因為它是經過數字簽名的。
什麼是時候使用JWT?
以下是 JSON Web Tokens 有用的一些場景:
-
授權:這是使用 JWT 最常見的場景。使用者登入後,每個後續請求都將包含 JWT,允許使用者訪問該令牌允許的路由、服務和資源。單點登入是當今廣泛使用 JWT 的一項功能,因為它的開銷很小,並且能夠輕鬆跨不同域使用。
-
資訊交換:JSON Web Tokens 是一種在各方之間安全傳輸資訊的好方法。因為 JWT 可以被簽名——例如,使用公鑰/私鑰對——你可以確定發件人就是他們所說的那樣。此外,由於使用標頭和有效負載計算簽名,因此您還可以驗證內容是否未被篡改
什麼是 JWT 結構?
在其緊湊形式中,JSON Web Tokens 由用點 (.
)分隔的三個部分組成,它們是:
- 標題
- 有效載荷
- 簽名
因此,JWT 通常如下所示。
xxxxx.yyyyy.zzzzz
讓我們分解不同的部分。
標題
標頭通常由兩部分組成:令牌的型別,即 JWT,以及正在使用的簽名演算法,例如 HMAC SHA256 或 RSA。
例如:{ "alg": "HS256", "typ": "JWT" }
然後,這個 JSON 被Base64Url編碼以形成 JWT 的第一部分。
有效載荷
令牌的第二部分是負載,其中包含宣告。宣告是關於實體(通常是使用者)和附加資料的宣告。
- 註冊宣告:這些是一組預定義的宣告,這些宣告不是強制性的,而是推薦的,以提供一組有用的、可互操作的宣告。其中一些是:iss(發行者)、exp(到期時間)、sub(主題)、aud(受眾)等等(想去了解的同志可以進去仔細研究研究)
- 公共宣告:這些可以由使用 JWT 的人隨意定義。但是為了避免衝突,它們應該在IANA JSON Web Token Registry中定義或定義為包含抗衝突名稱空間的 URI。
- 私人宣告:這些都是使用它們同意並既不是當事人之間建立共享資訊的自定義宣告註冊或公眾的權利要求。
一個示例有效載荷可能是:{ "sub": "1234567890", "name": "John Doe", "admin": true }
然後對有效負載進行Base64Url編碼以形成 JSON Web 令牌的第二部分。
簽名
要建立簽名部分,您必須獲取編碼的標頭、編碼的有效載荷、祕密、標頭中指定的演算法,並對其進行簽名。
例如,如果要使用 HMAC SHA256 演算法,則簽名將通過以下方式建立:HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
簽名用於驗證訊息在此過程中沒有更改,並且在使用私鑰簽名的令牌的情況下,它還可以驗證 JWT 的傳送者是它所說的那個人。
標題+有效載荷+簽名
------------------------------------------------------------------------------主體內容--------------------------------------------------------------------------------
本次開發使用ASP.NET Core,開發前應先在NuGet程式包管理器中下載Microsoft.AspNetCore.Authentication.JwtBearer(博主使用的是5.0.8版本)
安裝完畢後就可以程式碼中使用了,首先要在API對應的controller上引用該程式包:using Microsoft.AspNetCore.Authentication.JwtBearer;
在對應API(博主使用登入API)中使用寫入以下程式碼
//建立jwt //header var signingAlgorithm = SecurityAlgorithms.HmacSha256; //payload
//token資料 //自定義資料 var claims = new[] { new Claim("userId","123456") }; //signiture var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecurityKey"]);//自己的私鑰資訊 var signingkey = new SymmetricSecurityKey(secretByte); var signingCredentials = new SigningCredentials(signingkey, signingAlgorithm); var token = new JwtSecurityToken( issuer: _configuration["Authentication:Issure"], //釋出者 audience: _configuration["Authentication:Audience"], //接受者 claims,//該token內儲存的自定義欄位資訊 notBefore:DateTime.UtcNow,//token簽發時間 expires:DateTime.UtcNow.AddDays(1),//token過期時間 signingCredentials//用於簽發token的祕鑰演算法 );
string TokenStr = new JwtSecurityTokenHandler().WriteToken(token);
若在API中加入授權認證,就要在Startup.cs檔案中新增如下程式碼:
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(option => { var secretByte = Encoding.UTF8.GetBytes(Configuration["Authentication:SecurityKey"]); option.TokenValidationParameters = new TokenValidationParameters() { // 驗證釋出者 ValidateIssuer = true, // 讀配置Issure ValidIssuer = Configuration["Authentication:Issure"], // 驗證接收者 ValidateAudience = true, // 讀配置Audience ValidAudience = Configuration["Authentication:Audience"], // 驗證過期時間 ValidateLifetime = true, // 設定生成token的祕鑰 IssuerSigningKey = new SymmetricSecurityKey(secretByte) }; }); }
appsettings.json配置資訊如下:
這樣API每次的請求都會驗證header中帶的Authorization引數是否符合JWT的驗證規範。
眾所周知,在Swaager興起的時代,它同樣可以具備驗證JWT的功能,只需要在安裝好正常使用Swaager的基礎上,在Startup.cs檔案中新增如下程式碼:
services.AddSwaggerGen(options => { var securityScheme = new OpenApiSecurityScheme() { Description = "JWT認證授權,使用直接在下框中輸入Bearer {token}(注意兩者之間是一個空格)", Name = "Authorization",//JWT預設引數名稱 In = ParameterLocation.Header, //jwt預設存放Authorization資訊的位置(請求頭) //使用Authorize頭部 Type = SecuritySchemeType.Http,//使用ApiKey在除錯時需要將Bearer {token}全部加入value;使用Http在除錯時只需要把token值加入value即可。 //內容為以 bearer開頭 Scheme = "bearer", BearerFormat = "JWT"//header頭部bearer資訊格式轉化為JWT }; //把所有方法配置為增加bearer頭部資訊 var securityRequirement = new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" } }, new string[] {} } }; //註冊到swagger中 options.AddSecurityDefinition("bearerAuth", securityScheme); options.AddSecurityRequirement(securityRequirement); });
這樣就可以在Swaager中愉快的使用JWT驗證了。