JWT Encoder
使用HS256、HS384、HS512创建和签署JSON Web令牌
头部
有效负载
密钥
编码的JWT
您的密钥永远不会离开浏览器。所有签名都在客户端进行。
什么是JWT编码?
JWT编码是创建JSON Web Token的过程——一种紧凑、URL安全的字符串,包含用密钥签名的声明集合。结果是由RFC 7519定义的三部分令牌(头.有效负载.签名),服务器可以验证而无需维护会话状态。在线JWT编码允许你直接在浏览器中创建和签署令牌,用于测试和开发。
头部声明签名算法(如HS256)和令牌类型。有效负载包含声明——键值对,如主体(sub)、过期时间(exp)和应用程序需要的任何自定义数据。两部分都序列化为JSON,然后进行base64url编码。签名使用秘密密钥计算编码的头和有效负载,将所有三个部分绑定在一起。
与会话cookie不同,JWT是自包含的:验证者无需查询数据库或调用外部服务。这使得基于JWT的认证在REST API、微服务和单页应用中很流行,其中无状态授权降低延迟并简化水平扩展。
为什么使用JWT编码器?
手动生成JWT需要base64url编码、JSON序列化和HMAC计算。该工具立即处理所有三个步骤,让你专注于获取正确的声明。
JWT编码器用例
HS256 vs HS384 vs HS512:HMAC算法比较
三种算法都使用HMAC(基于哈希的消息认证码)与共享秘密。不同之处在于底层哈希函数,它影响签名长度和安全裕度。对于大多数应用程序,HS256提供足够的安全性。当合规要求(如FIPS-140)要求更强的哈希,或你的令牌涉及高价值授权决策时,选择HS384或HS512。
| 算法 | 哈希 | 签名 | 速度 | 典型用途 |
|---|---|---|---|---|
| HS256 | SHA-256 | 32 B | Fastest | General purpose, default for most libraries |
| HS384 | SHA-384 | 48 B | Fast | Higher security margin, FIPS-140 compliant |
| HS512 | SHA-512 | 64 B | Fast | Maximum HMAC security, large payloads |
标准JWT声明参考
RFC 7519定义七个注册声明。没有一个是必需的,但正确使用可以改进互操作性和安全性。exp声明特别重要——没有过期日期的令牌如果秘密未轮换,则无限期有效。
| 声明 | 名称 | 描述 | 示例 |
|---|---|---|---|
| iss | Issuer | Who issued the token | "auth.example.com" |
| sub | Subject | Who the token represents | "user-123" |
| aud | Audience | Intended recipient service | "api.example.com" |
| exp | Expiration | Unix timestamp — token invalid after this time | 1717203600 |
| nbf | Not Before | Unix timestamp — token invalid before this time | 1717200000 |
| iat | Issued At | Unix timestamp when the token was created | 1717200000 |
| jti | JWT ID | Unique token identifier for revocation tracking | "a1b2c3d4" |
代码中的JWT编码
这些示例显示如何以编程方式创建和签署JWT。每个片段都生成有效的HS256签署令牌。对于生产系统,始终设置exp声明并使用至少256位的密码安全秘密。
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..."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}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: ... }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...
}