理解JWT登入機制

Darren
8 min readDec 12, 2023

--

在現代網站開發中,JSON Web Tokens(JWT)是一種流行的身份驗證和授權機制。以下簡單說明JWT的流程

用戶身份驗證

  1. 用戶輸入資料:用戶在登入表單中輸入他們的憑證,例如用戶名和密碼。
  2. 伺服器驗證:伺服器接收到憑證後,會在資料庫中驗證用戶的身份。

生成JWT

  1. 成功驗證後:一旦用戶被成功驗證,伺服器會創建一個JWT。
  2. JWT結構:JWT通常包含三部分:頭部(Header)、有效負載(Payload)、和簽名(Signature)。
  • 頭部:指定了令牌的類型(通常是JWT)和所使用的簽名算法,如HMAC SHA256或RSA。
  • 有效負載:包含聲明(claims),聲明是關於實體(通常是用戶)和其他數據的陳述。例如,用戶ID、用戶名、過期時間等。
  • 簽名:對頭部和有效負載進行簽名,以驗證消息在傳輸過程中未被篡改。

發送JWT給用戶

  1. 客戶端存儲:伺服器將JWT發送回用戶,用戶端應用程式(如瀏覽器)會將其存儲在本地,通常是在Cookie或LocalStorage中。

JWT的使用

  1. 隨請求發送:之後,當用戶向伺服器發送請求時,會將JWT附加在HTTP請求的授權頭部中。
  2. 伺服器驗證JWT:伺服器會驗證接收到的JWT的簽名,以確保它是有效和可信的。
  3. 授權和存取控制:伺服器根據JWT中的資訊(如用戶角色)進行授權和存取控制。

JWT過期處理

  1. 過期機制:JWT通常包含過期時間。一旦過期,用戶需要重新登入以獲得新的JWT。
  2. 刷新令牌:在某些實現中,系統可能會提供刷新令牌(Refresh Token),用於在不需要用戶重新登入的情況下更新JWT。

優點與考量

  • 無狀態和可擴展性:由於JWT自包含所有用戶信息,伺服器不需要維護用戶的登入狀態,這對於構建可擴展的應用程式很有幫助。
  • 安全性考量:雖然JWT提供了方便的身份驗證機制,但它也帶來了安全挑戰,如JWT的安全存儲、防止XSS和CSRF攻擊等。

如何安裝和使用JWT

安裝底下套件

Microsoft.AspNetCore.Authentication.JwtBearer
System.IdentityModel.Tokens.Jwt

或下指令

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

1.建立一個使用者模型

public class User
{
public string Username { get; set; }
public string Password { get; set; }
}

2. 創建一個控制器來處理登入請求

using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly string _key = "ThisIsASecretKeyForJwt";

[HttpPost("login")]
public IActionResult Login([FromBody] User user)
{
// 模擬使用者驗證
if (user.Username == "admin" && user.Password == "password")
{
var token = GenerateJwtToken(user.Username);
return Ok(new { Token = token });
}

return Unauthorized("Invalid credentials");
}

private string GenerateJwtToken(string username)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_key));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
issuer: "yourdomain.com",
audience: "yourdomain.com",
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds
);

return new JwtSecurityTokenHandler().WriteToken(token);
}
}

3. 配置 JWT 中間件驗證

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// 添加 JWT 驗證中間件
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "yourdomain.com",
ValidAudience = "yourdomain.com",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ThisIsASecretKeyForJwt"))
};
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

4. 建立一個受保護的 API 端點

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ProtectedController : ControllerBase
{
[HttpGet]
[Authorize]
public IActionResult GetSecret()
{
var username = User.Identity?.Name;
return Ok($"Hello, {username}! This is a protected message.");
}
}

測試
啟動應用程式,發送一個登入請求:

URL: http://localhost:5000/api/auth/login
Method: POST
Body:
{
"username": "admin",
"password": "password"
}

使用返回的 Token 測試受保護的端點:

URL: http://localhost:5000/api/protected
Method: GET
Headers:Authorization: Bearer [Your JWT Token]

總結

JWT這套機制具有輕量、跨平台的優勢,在現代應用中實現身份認證與授權是不可或缺的套件。趕快動手試試吧!

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Darren
Darren

Written by Darren

喜歡研究技術的廢材工程師

No responses yet

Write a response