Bộ mã hóa JWT

Tạo và ký JSON Web Tokens với HS256, HS384, HS512

Tiêu đề

Chạy cục bộ · An toàn để dán thông tin bí mật

Dữ liệu

Chạy cục bộ · An toàn để dán thông tin bí mật

Khóa bí mật

Chạy cục bộ · An toàn để dán thông tin bí mật

JWT được mã hóa

Output will appear here…

Khóa bí mật của bạn không bao giờ rời khỏi trình duyệt. Tất cả chữ ký được thực hiện phía máy khách.

Thử thêm:Giải mã JWT

JWT Encoding là gì?

JWT encoding là quá trình tạo JSON Web Token — một chuỗi nhỏ gọn và an toàn URL chứa một tập hợp các yêu cầu được ký bằng khóa mật mã. Kết quả là một token ba phần (header.payload.signature) được định nghĩa bởi RFC 7519 mà các máy chủ có thể xác minh mà không cần duy trì trạng thái phiên.

Header khai báo thuật toán ký (ví dụ HS256) và loại token. Payload chứa các claim — các cặp key-value như chủ thể (sub), thời gian hết hạn (exp) và bất kỳ dữ liệu tùy chỉnh nào ứng dụng của bạn cần. Cả hai phần đều được tuần tự hóa dưới dạng JSON, sau đó được mã hóa base64url. Signature được tính toán trên header và payload đã mã hóa bằng khóa bí mật, liên kết cả ba phần lại với nhau.

Không giống cookie phiên, JWT có tính tự chứa: bên xác minh không cần truy vấn cơ sở dữ liệu hay gọi dịch vụ bên ngoài. Điều này làm cho xác thực dựa trên JWT trở nên phổ biến trong REST API, microservice và ứng dụng trang đơn, nơi phân quyền không trạng thái giảm độ trễ và đơn giản hóa mở rộng theo chiều ngang.

Tại sao dùng JWT Encoder?

Tạo JWT thủ công đòi hỏi mã hóa base64url, tuần tự hóa JSON và tính toán HMAC. Công cụ này xử lý cả ba bước ngay lập tức để bạn có thể tập trung vào việc thiết lập đúng các claim.

Tạo Token tức thì
Chỉnh sửa header, payload và bí mật — JWT đã ký cập nhật theo thời gian thực. Không cần bước build, không cài thư viện, không viết boilerplate code.
🔒
Nhiều thuật toán HMAC
Chuyển đổi giữa HS256, HS384 và HS512 chỉ với một cú nhấp. Header cập nhật tự động và signature được tính toán lại ngay lập tức.
🛡️
Xử lý ưu tiên quyền riêng tư
Tất cả ký kết diễn ra trong trình duyệt của bạn bằng Web Crypto API. Khóa bí mật và dữ liệu payload của bạn không bao giờ rời khỏi máy — không có máy chủ, không có nhật ký, không có rủi ro.
📋
Trợ giúp Claim một cú nhấp
Thêm dấu thời gian iat, exp+1h hoặc exp+24h chỉ với một nút. Không cần tính Unix timestamp thủ công hay tra cứu thời gian epoch hiện tại.

Trường hợp sử dụng JWT Encoder

Kiểm thử xác thực Frontend
Tạo token với các claim và thời gian hết hạn cụ thể để kiểm thử luồng đăng nhập, logic làm mới token và bảo vệ route mà không cần chạy máy chủ xác thực backend.
Phát triển API Backend
Tạo token kiểm thử với các claim sub, aud và scope tùy chỉnh để kiểm tra middleware phân quyền, kiểm soát truy cập dựa trên vai trò và kiểm tra quyền trong quá trình phát triển cục bộ.
Pipeline DevOps & CI/CD
Tạo token dịch vụ có thời hạn ngắn cho script triển khai, kiểm thử tích hợp hoặc giao tiếp giữa các dịch vụ, nơi một luồng OAuth đầy đủ sẽ thêm độ phức tạp không cần thiết.
Kiểm thử QA & Thủ công
Tạo token với các claim biên — token hết hạn, thiếu trường, audience sai — để xác minh rằng API của bạn trả về đúng phản hồi HTTP 401 hoặc 403.
Kiểm toán bảo mật
Tạo token được ký với các thuật toán và độ dài bí mật khác nhau để xác nhận rằng logic xác minh của bạn từ chối đúng các signature yếu hoặc không khớp.
Học tập & Tạo mẫu
Sinh viên và lập trình viên mới làm quen với JWT có thể thử nghiệm với các trường header, cấu trúc claim và thuật toán ký để hiểu cách mỗi phần của token hoạt động.

HS256 vs HS384 vs HS512: So sánh thuật toán HMAC

Cả ba thuật toán đều dùng HMAC (Hash-based Message Authentication Code) với bí mật chung. Sự khác biệt là hàm băm bên dưới, ảnh hưởng đến độ dài signature và mức độ bảo mật. Đối với hầu hết ứng dụng, HS256 cung cấp đủ bảo mật. Chọn HS384 hoặc HS512 khi yêu cầu tuân thủ (ví dụ FIPS-140) bắt buộc dùng hàm băm mạnh hơn hoặc khi token của bạn mang các quyết định phân quyền có giá trị cao.

Thuật toánHàm bămSignatureTốc độSử dụng điển hình
HS256SHA-25632 BFastestGeneral purpose, default for most libraries
HS384SHA-38448 BFastHigher security margin, FIPS-140 compliant
HS512SHA-51264 BFastMaximum HMAC security, large payloads

Tham chiếu các Claim JWT chuẩn

RFC 7519 định nghĩa bảy claim đã đăng ký. Không có claim nào bắt buộc, nhưng sử dụng đúng chúng sẽ cải thiện khả năng tương tác và bảo mật. Claim exp đặc biệt quan trọng — token không có thời hạn hết hạn sẽ có hiệu lực vô thời hạn nếu bí mật không được thay đổi.

ClaimTênMô tảVí dụ
issIssuerWho issued the token"auth.example.com"
subSubjectWho the token represents"user-123"
audAudienceIntended recipient service"api.example.com"
expExpirationUnix timestamp — token invalid after this time1717203600
nbfNot BeforeUnix timestamp — token invalid before this time1717200000
iatIssued AtUnix timestamp when the token was created1717200000
jtiJWT IDUnique token identifier for revocation tracking"a1b2c3d4"

JWT Encoding trong Code

Các ví dụ này cho thấy cách tạo và ký JWT theo chương trình. Mỗi đoạn code tạo ra token HS256 hợp lệ. Đối với hệ thống sản xuất, luôn đặt claim exp và dùng bí mật ngẫu nhiên mật mã có ít nhất 256 bit.

JavaScript (Web Crypto API)
async function signJWT(payload, secret, alg = 'HS256') {
  const header = { alg, typ: 'JWT' }
  const enc = new TextEncoder()

  // Base64url encode header and payload
  const b64url = (obj) =>
    btoa(JSON.stringify(obj)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

  const h = b64url(header)
  const p = b64url(payload)

  // Sign with HMAC-SHA256
  const key = await crypto.subtle.importKey(
    'raw', enc.encode(secret),
    { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
  )
  const sig = await crypto.subtle.sign('HMAC', key, enc.encode(`${h}.${p}`))
  const s = btoa(String.fromCharCode(...new Uint8Array(sig)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

  return `${h}.${p}.${s}`
}

// Usage
const token = await signJWT(
  { sub: 'user-123', name: 'Alice', iat: Math.floor(Date.now() / 1000) },
  'your-256-bit-secret'
)
// → "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOi..."
Python (PyJWT)
import jwt
import time

payload = {
    "sub": "user-123",
    "name": "Alice",
    "iat": int(time.time()),
    "exp": int(time.time()) + 3600,  # expires in 1 hour
}

# Sign with HS256 (default)
token = jwt.encode(payload, "your-256-bit-secret", algorithm="HS256")
# → "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOi..."

# Verify and decode
decoded = jwt.decode(token, "your-256-bit-secret", algorithms=["HS256"])
# → {"sub": "user-123", "name": "Alice", "iat": 1717200000, "exp": 1717203600}
Node.js (jsonwebtoken)
const jwt = require('jsonwebtoken')

const payload = {
  sub: 'user-123',
  name: 'Alice',
  role: 'admin',
}

// Sign — iat is added automatically
const token = jwt.sign(payload, 'your-256-bit-secret', {
  algorithm: 'HS256',
  expiresIn: '1h',    // sets exp claim
  issuer: 'auth.example.com',  // sets iss claim
})

// Verify
const decoded = jwt.verify(token, 'your-256-bit-secret')
// → { sub: 'user-123', name: 'Alice', role: 'admin', iat: ..., exp: ... }
Go (golang-jwt)
package main

import (
    "fmt"
    "time"
    "github.com/golang-jwt/jwt/v5"
)

func main() {
    claims := jwt.MapClaims{
        "sub":  "user-123",
        "name": "Alice",
        "iat":  time.Now().Unix(),
        "exp":  time.Now().Add(time.Hour).Unix(),
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    signed, _ := token.SignedString([]byte("your-256-bit-secret"))
    fmt.Println(signed)
    // → eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOi...
}

Câu hỏi thường gặp

Sự khác biệt giữa JWT encoding và JWT decoding là gì?
JWT encoding tạo token đã ký từ header, payload và khóa bí mật. JWT decoding đảo ngược quá trình — đọc header và payload được mã hóa base64url trở lại thành JSON. Decoding không yêu cầu bí mật; encoding thì luôn cần vì signature phải được tính toán.
Khóa bí mật JWT nên có độ dài bao nhiêu?
Đối với HS256, dùng bí mật ít nhất 256 bit (32 byte). Đối với HS384, dùng ít nhất 384 bit (48 byte). Đối với HS512, dùng ít nhất 512 bit (64 byte). Bí mật ngắn hơn về mặt kỹ thuật vẫn được hầu hết thư viện chấp nhận nhưng làm giảm mức độ bảo mật thực tế của signature HMAC. Tạo bí mật bằng trình tạo ngẫu nhiên mật mã, không dùng cụm mật khẩu do con người chọn.
Có an toàn khi dùng công cụ này với khóa bí mật thật không?
Công cụ này xử lý mọi thứ trong trình duyệt của bạn bằng Web Crypto API — không có dữ liệu nào được gửi đến bất kỳ máy chủ nào. Tuy nhiên, tránh dán bí mật sản xuất vào bất kỳ công cụ web nào như một biện pháp bảo mật chung. Để quản lý khóa sản xuất, dùng biến môi trường hoặc trình quản lý bí mật như HashiCorp Vault hoặc AWS Secrets Manager.
Tôi nên dùng HS256 hay RS256 cho ứng dụng của mình?
Dùng HS256 khi cùng một dịch vụ vừa tạo vừa xác minh token — nhanh hơn và đơn giản hơn. Dùng RS256 (bất đối xứng) khi các dịch vụ bên thứ ba cần xác minh token của bạn mà không có khả năng tạo chúng. RS256 phổ biến trong các nhà cung cấp OAuth 2.0, OpenID Connect và kiến trúc SaaS đa tenant.
Tại sao JWT của tôi hết hạn ngay sau khi tạo?
Claim exp dùng Unix timestamp tính bằng giây, không phải mili giây. Nếu bạn đặt exp thành Date.now() (trả về mili giây), token sẽ xuất hiện hết hạn hàng nghìn năm trong tương lai — hoặc nếu bạn vô tình dùng giá trị mili giây khi giây được mong đợi, thư viện có thể hiểu là đã hết hạn. Luôn dùng Math.floor(Date.now() / 1000) trong JavaScript hoặc int(time.time()) trong Python.
Tôi có thể đặt dữ liệu nhạy cảm trong JWT payload không?
Bạn có thể, nhưng không nên. JWT payload được mã hóa base64url, không phải mã hóa — bất kỳ ai có token đều có thể đọc các claim. Không lưu mật khẩu, số thẻ tín dụng hoặc dữ liệu cá nhân trong payload. Nếu bắt buộc phải bao gồm thông tin nhạy cảm, hãy dùng JWE (JSON Web Encryption) được định nghĩa trong RFC 7516, mã hóa toàn bộ payload.
Điều gì xảy ra nếu tôi thay đổi payload sau khi ký?
Signature sẽ không hợp lệ. Signature HMAC được tính toán trên các byte chính xác của header và payload đã mã hóa. Bất kỳ thay đổi nào — kể cả thêm một dấu cách hoặc thay đổi một ký tự — đều tạo ra signature hoàn toàn khác. Một bên xác minh được triển khai đúng cách sẽ từ chối token với lỗi signature không khớp.