前言

上一章我們介紹了 JWT 的基本原理,接下來我們會建立一個 WebAPI 並透過他發行 JWT Token,然後將導入 Token 驗證的機制

建立 WebAssembly 專案

  1. 開啟 Visual Studio 點選建立新專案並點選 Blazor WebAssembly 選擇Blazor WebAssembly專案

  2. 勾選 裝載在 ASP.NET Core 上 勾選 裝載在 ASP.NET Core

  3. 完成專案建立

發行 Token

完成專案的建置後,我們要在網頁的後端做 JWT

  1. 安裝 NuGet 套件到 Blazor.Jwt.Server 專案內
1
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
  1. 在 Blazor.Jwt.Server 專案內,加入一個 API Controller

  2. 這邊我取名為 AuthorizeController.cs

  3. 修改Route Attribute

1
  [Route("api/[controller]/[action]")]
  1. 寫一個 GetToken 方法

這邊為了示範所以將邏輯都放在 Controller 內

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        [HttpGet]
        public IActionResult GetToken(string userName)
        {
            var key = "2022/09/28 IThome 鐵人賽";
            var claims = new List<Claim>
            {
                // 使用者名稱
                new (JwtRegisteredClaimNames.Sub,userName),
                // Token Id
                new (JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())
            };
            var claimsIdentity = new ClaimsIdentity(claims);
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
            var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = "發行者",
                Subject = claimsIdentity,
                Expires = DateTime.UtcNow.AddMinutes(30),
                SigningCredentials = signingCredentials
            };
            var tokenHandler = new JwtSecurityTokenHandler();
            var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            return Ok(tokenHandler.WriteToken(securityToken));
        }
  1. 呼叫API 取得Token https://localhost:7102/api/Authorize/GetToken?username=JimWang

恭喜 ! 做到這邊就成功發行了 JWT Token ,我們拿去解析

  • nbf 代表從這個時間以前無效
  • exp 有效期限
  • iat 發行時間

驗證 Token

我們發行了 Token 下一個問題點在於,當使用者拿著 Token 來的時候,我該怎麼驗證這份 Token

  1. 一樣是 Blazor.Jwt.Server 專案內,在Program.cs中加入服務
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
            ValidateIssuer = true,
            ValidIssuer = "發行者",
            ValidateLifetime = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("2022/09/28 IThome 鐵人賽"))
        };
    });

這邊的 option 有非常多的設定可以調整,要注意需要填入簽名使用的 key,如果有驗證發行者alidateIssuer = true,也需要填入生產Token時的發行者

  1. 加入驗證服務
1
builder.Services.AddAuthorization();
  1. 最後在下方app的部分加入兩行
1
2
app.UseAuthentication();
app.UseAuthorization();

注意順序不可以錯誤 先驗證再授權!!!

套用 JWT

我們完成了發行以及驗證,可是好像還沒有用上,最後一個步驟做整合,讓我們的 WebAPI 受到身分驗證的保護

  1. 回到 AuthorizeController.cs 再加入一個新的 action
1
2
3
4
5
6
        [HttpGet]
        [Authorize]
        public IActionResult GetUserInfo()
        {
            return Ok("取得使用者資料");
        }
  1. 呼叫 GetUserInfo() 會發現回覆的 HttpStatusCode 從 200 變成 401,因為我這一個請求沒有帶入Token,所以伺服器直接回覆我 Code 401,接著我們再試著帶入 Token 並且執行

  2. 帶入 Token

  3. 呼叫成功

小結

明天我們會在 Blazor WebAssembly 練習取得 Token ,並且請求(Request) 中一起帶入 Token,取得伺服器的資源