内容简介:為了保護 WebAPI 僅提供合法的使用者存取,有很多機制可以做,透過 JWT (JSON Web Token) 便是其中一種方式,這篇示範如何使用官方所提供的順道一提,要產生 JWT Token 有很多套件可以幫助開發者快速建立,使用 Visual Studio 2019 建立 ASP.NET Core WebAPI 專案後,首先修改
為了保護 WebAPI 僅提供合法的使用者存取,有很多機制可以做,透過 JWT (JSON Web Token) 便是其中一種方式,這篇示範如何使用官方所提供的 System.IdentityModel.Tokens.Jwt
擴充套件,處理呼叫 API 的來源是否為合法的使用者身分。
順道一提,要產生 JWT Token 有很多套件可以幫助開發者快速建立, JWT
這個 NuGet 套件就是其中一個,但這裡我使用官方所提供的 System.IdentityModel.Tokens.Jwt
擴充套件來處理,雖然這是官方提供的版本,但寫起來一點也不困難。
建立專案
使用 Visual Studio 2019 建立 ASP.NET Core WebAPI 專案後,首先修改 Startup.cs
中的 ConfigureServices
方法,設定這個 WebAPI 站台要使用哪種方式來驗證 HTTP Request 是否合法,程式碼如下:
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // STEP1: 設定用哪種方式驗證 HTTP Request 是否合法 services // 檢查 HTTP Header 的 Authorization 是否有 JWT Bearer Token .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // 設定 JWT Bearer Token 的檢查選項 .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidateAudience = true, ValidAudience = Configuration["Jwt:Issuer"], ValidateLifetime = true, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])) }; }); }
這裡我們設定系統在驗證 JWT Token 時,必須要符合以下 4 個條件:
- 相同的 Issuer 設定值
- 相同的 Audience 設定值
- 驗證 Token 有效期限
- 符合對稱式加密的簽章
接者一樣在 Startup.cs
中的 Configure
加入驗證權限用的 Middleware,讓每次進來的 HTTP Request 都會經過此層驗證機制,程式碼如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // 略... // STEP2: 使用驗證權限的 Middleware app.UseAuthentication(); app.UseHttpsRedirection(); app.UseMvc(); }
如此一來網站的基本設定就搞定了。
取得 JWT Token
要如何產生 JWT Token 呢?這裡我們建立了一個 AuthController
控制器來產生所需要的 JWT Token,流程如下:
- 身分驗證
- 建立使用者聲明資訊
- 取得加密金鑰
- 建立 JWT Token
身分驗證是你的需求自行實作,驗證後可將取得的使用者資訊(非機敏資訊)包進使用者的 Claim 聲明中,這些資訊將會是 JWT Payload 的一部分,這裡的 Claim 聲明資訊也可以根據你的需求客制增加。
我們知道 JWT 是用三部分 Header、Payload 和 Signature,並使用 點 (.)將三個部分連結起來成為一個字串,Signature 這部分會是 Header、Payload 加上一組 Secret 做雜湊運算產生出來的,用來驗證整個 JWT 資訊是沒有被竄改過。加密金鑰這段雖然是選用,但還是相當建議加上去,增加安全強度。
接著透過 System.IdentityModel.Tokens.Jwt
這個命名空間底下的 JwtSecurityTokenHandler
來產生 JWT Token,而 JWT Token 的內容描述則交由 SecurityTokenDescriptor
來組合,在 JWT Token 的內容描述中,請根據需求做調整。
如此一來就可以產生所需要的 JWT Token 了。
[Route("api/[controller]")] [ApiController] public class AuthController : ControllerBase { private readonly IConfiguration _config; public AuthController(IConfiguration configuration) { _config = configuration; } // GET api/auth/login [HttpGet, Route("login")] public IActionResult Login(string name) { // STEP0: 在產生 JWT Token 之前,可以依需求做身分驗證 // STEP1: 建立使用者的 Claims 聲明,這會是 JWT Payload 的一部分 var userClaims = new ClaimsIdentity(new[] { new Claim(JwtRegisteredClaimNames.NameId, name), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim("CustomClaim", "Anything You Like") }); // STEP2: 取得對稱式加密 JWT Signature 的金鑰 // 這部分是選用,但此範例在 Startup.cs 中有設定 ValidateIssuerSigningKey = true 所以這裡必填 var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); // STEP3: 建立 JWT TokenHandler 以及用於描述 JWT 的 TokenDescriptor var tokenHandler = new JwtSecurityTokenHandler(); var tokenDescriptor = new SecurityTokenDescriptor { Issuer = _config["Jwt:Issuer"], Audience = _config["Jwt:Issuer"], Subject = userClaims, Expires = DateTime.Now.AddMinutes(30), SigningCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256) }; // 產出所需要的 JWT Token 物件 var securityToken = tokenHandler.CreateToken(tokenDescriptor); // 產出序列化的 JWT Token 字串 var serializeToken = tokenHandler.WriteToken(securityToken); return new ContentResult() { Content = serializeToken }; } }
如何使用
使用上非常簡單,只要掛上需要的裝飾器即可,這裡建立了 ValuesController
做測試,分別掛上 [AllowAnonymous]
和 [Authorize]
,前者是給匿名登入使用,也就是不需要有 JWT Token 也能執行,後者則必須要在 HTTP 的 Authorization Header 必須設定合法的 JWT Bearer Token 才能使用。
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values/anonymous /// <summary>使用匿名登入,無視於身分驗證</summary> [AllowAnonymous] [HttpGet, Route("anonymous")] public IActionResult Anonymous() { return new ContentResult() { Content = $@"For all anonymous." }; } // GET api/values/authorize /// <summary>使用身分驗證,HTTP 的 Authorization Header 必須設定合法的 JWT Bearer Token 才能使用</summary> [Authorize] [HttpGet, Route("authorize")] public IActionResult All() { return new ContentResult() { Content = $@"For all client who authorize." }; } }
這個驗證裝飾器還可以有很多種玩法,例如根據所建立的驗證 Policy 做驗證,或根據使用者 Claim 聲明的角色做驗證,提供了很大的彈性來處理。
JwtRegisteredClaimNames 屬性說明
在建立使用者的 Claims 聲明時,我們會用到很多 JwtRegisteredClaimNames
結構型別,來取得是先定義好的字串,在 System.IdentityModel.Tokens.Jwt
命名空間中的 JwtRegisteredClaimNames
定義了很多 JWT 會用到的聲明,但 官方文件
說明相當的少,自行整理了如下:
聲明欄位 | 說明 | 連結 |
---|---|---|
Jti | 表示 JWT ID,Token 的唯一識別碼 | http://tools.ietf.org/html/rfc7519#section-4 |
Iss | 表示 Issuer,發送 Token 的發行者 | http://tools.ietf.org/html/rfc7519#section-4 |
Iat | 表示 Issued At,Token 的建立時間 | http://tools.ietf.org/html/rfc7519#section-4 |
Exp | 表示 Expiration Time,Token 的逾期時間 | http://tools.ietf.org/html/rfc7519#section-4 |
Sub | 表示 Subject,Token 的主體內容 | http://tools.ietf.org/html/rfc7519#section-4 |
Aud | 表示 Audience,接收 Token 的觀眾 | http://tools.ietf.org/html/rfc7519#section-4 |
Typ | 表示 Token 的類型,例如 JWT 表示 JSON Web Token 類型 | http://tools.ietf.org/html/rfc7519#section-4 |
Nbf | 表示 Not Before,定義在什麼時間之前,不可用 | http://tools.ietf.org/html/rfc7519#section-4 |
Actort | 識別執行授權的代理是誰 | http://tools.ietf.org/html/rfc7519#section-4 |
Prn | http://tools.ietf.org/html/rfc7519#section-4 | |
Nonce | http://tools.ietf.org/html/rfc7519#section-4 | |
NameId | 使用者識別碼 | http://tools.ietf.org/html/rfc7519#section-4 |
FamilyName | 使用者姓氏 | http://tools.ietf.org/html/rfc7519#section-4 |
GivenName | 使用者名字 | http://tools.ietf.org/html/rfc7519#section-4 |
Gender | 使用者性別 | http://tools.ietf.org/html/rfc7519#section-4 |
使用者的電子郵件 | http://tools.ietf.org/html/rfc7519#section-4 | |
Birthdate | 使用者生日 | http://tools.ietf.org/html/rfc7519#section-4 |
Website | 使用者的網站 | http://tools.ietf.org/html/rfc7519#section-4 |
CHash | http://tools.ietf.org/html/rfc7519#section-4 | |
UniqueName | http://tools.ietf.org/html/rfc7519#section-4 | |
AtHash | http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken | |
Acr | http://openid.net/specs/openid-connect-core-1_0.html#IDToken | |
Amr | http://openid.net/specs/openid-connect-core-1_0.html#IDToken | |
Azp | http://openid.net/specs/openid-connect-core-1_0.html#IDToken | |
AuthTime | http://openid.net/specs/openid-connect-core-1_0.html#IDToken | |
Sid | http://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout |
有些定義的聲明欄位很難找到說明,有找到相關資訊再陸續補充。
程式碼
關於本篇文章完整的程式碼發布於 GitHub: poychang/Demo-WebAPI-Jwt-Auth
,請參考裡面的 SimpleJwtAuth
專案。
參考資料:
以上所述就是小编给大家介绍的《在 ASP.NET Core WebAPI 中使用 JWT 驗證》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- RecyclerView使用指南(一)—— 基本使用
- 如何使用Meteorjs使用URL参数
- 使用 defer 还是不使用 defer?
- 使用 Typescript 加强 Vuex 使用体验
- [译] 何时使用 Rust?何时使用 Go?
- UDP协议的正确使用场合(谨慎使用)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。