引子
前面說了用第三方類庫生成JWT的故事,給我帶來了很大的方便,並且我也承諾要寫一篇用常規方法生成JWT的文章(一般都是用微軟官方的類庫),因此才有了這篇文章。
另外,在前面的文章中,我要糾正一下一些錯誤JWT的整個結構決定了JWT只能作為臨時的授權認證解決方案,如果對使用者的機密性要求比較高,必須用有狀態控制管理的解決方案,JWT只能作為一般性方案使用,它的應用場合主要是由多個WebAPI構成的多程式多執行緒多介面這樣的微服務架構,是為了解決使用狀態管理帶來的不便才應用而生,一般JWT必須和HTTPS配合才會具有安全性。這是因為JWT作為一種可被破解的資料,只有TLS加密後,才不會被真正破解。
在微軟的Indentiy認證框架中(我個人感覺應該叫ASP.NET Core Indentity),MVC和WebAPI雖然使用不同的Nuget包,但本質是一樣的……廢話不多說了,直接正題開始:有請我們的主角:JwtSecurityTokenHandler(從名字中就知道它和資料庫操作有關,JWT中的資料一般都是來自使用者資料庫,helper一般用來表示資源管理),後面我們會透過它來實現JWT的生成。
實施
和前面一樣,我們這裡主要講解最常用的非對稱演算法的JWT,這裡採用的演算法是RSA,當然你也可以採用其他演算法來達到目標。
首先需要安裝nuget包Microsoft.AspNetCore.Authentication.JwtBearer
,當然,有的文章會讓你安裝一個System.IdentityModel.Tokens.JWT
的包,這個完全不需要,因為前面的包已經包含後者了,你只要在引用包以後,構建一下工程,在dubug目錄裡面找到專案生成檔案,就會發現這個dll被放進去了。
由於ASP.NET Core是以依賴注入為主的,而這個包作為一個Service(服務),需要使用其自身提供的擴充套件方法來注入ASP.NET Core 的WebApplication的Service物件(IOC容器)中進行集中管理。
點選檢視實現程式碼
builder.Services.AddAuthentication()..AddJwtBearer(jwtOptions =>{
jwtOptions.Authority = "https://jwtserver.test.net";
//jwtOptions.Audience = "jwtresouce";
jwtOptions.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],//發行者
ValidAudience = builder.Configuration["Jwt:Audience"], //訂閱者
IssuerSigningKey = new RsaSecurityKey(RSA.Create(2048)) //jwt簽名演算法
};
})
- 先建立一個用來生成JWT的
JwtSecurityTokenHandler
物件,為後面的工作提供基礎 - 再建立一個陣列,用來存放使用者資訊
- 建立
SecurityTokenDescriptor
物件,設定JWT的加密演算法,有效期等屬性 - 呼叫之前建立的
JwtSecurityTokenHandler
物件的CreateToken
方法,建立一個令牌物件,再呼叫WriteToken
方法,獲得到字串格式的JWT - 返回結果
點選檢視實現程式碼
[HttpPost]
public string CreateJwtSecurityToken()
{
var tokenHandler = new JwtSecurityTokenHandler();
var mookdata = new Dictionary<string, string>();
mookdata[ClaimTypes.Name] = "John Doe";
mookdata[ClaimTypes.Email] = "johndoe@example.com";
mookdata[ClaimTypes.Role] = "vistor";
var claims = new Claim[mookdata.Count - 1];
foreach (var item in mookdata)
{
for (int i = 0; i < claims.Length; i++)
{
claims[i] = new Claim(item.Key, item.Value);
}
}
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new RsaSecurityKey(RSA.Create(2048)),
SecurityAlgorithms.RsaSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return tokenString;
}
總結
上述講到的方法一般都是比較常用的方法(這個好像是來自微軟官方文件),先對於上篇文章,它相對比較靈活,不會涉及到x509證書的問題,而且解決方案比較多,容易應用。
關於生成JWT,我也是簡單的瞭解和使用,因此層次不少太深,如果讀者在其中發現了問題,也歡迎各位提出寶貴的意見,謝謝。
關於JWT,我想說這只是WebAPI授權鑑權的開端,不是終點,如果有時間,我會再寫一篇結合JWT來授權鑑權的文章,來更好的理解JWT的應用,希望我的文章會給您帶來幫助,讓我們一起期待吧!