先簡單說下JSON Web Token, 然後使用.NET Core内置的JWT驗證機制.
Demo Source Code
AspNetCore JwtBearer Source Code
JSON Web Token
是什麼
-
JSON Web Token(JWT)是一個開放标準(RFC 7519),它定義了一種緊湊且獨立的方式,用于在各方之間作為JSON對象安全地傳輸資訊。
資料格式為: Header.Payload.Signature
-
生成JWT Token
JWT的資料簽名(Signature)是對Payload中的資料, 按照Header中指定的加密算法, 加上Server端的密鑰進行簽名生成的.
- Signature = Payload + Algorithm(Header) + Security(私有)
- 通過簽名反推出密鑰的可能性很小, 并且密鑰是Server端私有的, 可以定期更換
使用
JWT多用來驗證請求的有效性
下面是簡單的使用流程
- 使用者post{username, password}到server, 請求token, server生成後傳回token
- 得到token後, client端儲存token: cookie/sessionStorage/localStorage
- 以後每當發起請求, 将token放到請求頭: headers: { ‘Authorization’:
},token
- server收到請求後, 會根據密鑰及token中的payload生成新的signature并與token的中signature進行對比, 二者一緻則驗證通過
優勢
-
token的自驗證性,減輕了服務端壓力
server通過JWT的header, payload和signature就可以驗證使用者, 不需要再去查詢資料庫
-
JWT不僅可以用于認證,也可以用于交換資訊。有效使用JWT,可以降低伺服器查詢資料庫的次數
JWT的payload中可以存儲使用者名, 權限, 過期時間等非安全資訊, 解析token本身就可以取得
- JWT的自驗證性, 非常适合單頁面程式, 多點登入
- 通過将token放在請求頭并使用https通路, 防範跨站腳本攻擊(xss)和跨站攻擊(csrf)
- 通過生成refresh token驗證access token的實效性, 控制access token的有效時間, 解決無法回收token通路權限的問題
劣勢
- 因為自驗證性, 無法及時回收通路權限, token一旦被分發, 就會一直有效, 可以通過減少生效時間使用
.NET Core的JWT驗證機制
.NET Core的JWT驗證機制基于authentication中間件, 注入JWT服務後, 需要authenrize的請求都會使用token驗證
Demo Source Code
AspNetCore JwtBearer Source Code
- 注入内置的JWT service
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey("your secret key"),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
- 生成有效的token
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("your token payload")
}),
// token的有效時間
Expires = DateTime.UtcNow.AddMinutes(),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
result = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));
4. 通過屬性标簽[Authorize]添加token驗證的請求
[Authorize]支援class級别和接口級别的指定
[Authorize]
public class RepairController : ControllerBase
[Authorize]
[HttpGet("data")]
public ActionResult Get()