提示:本网站现在为维护调试状态

JWT 认证安全最佳实践 + OAuth2 vs SAML

Choyeon
Choyeon
2026年9月12日 1 分钟阅读 275 阅读
590 字 2,317 字符 更新于 2026年11月8日
JWT 认证安全最佳实践 + OAuth2 vs SAML
目录

JWT 因其无状态、跨服务易用被广泛采用,但配置不严谨会成攻击重灾区。现代系统常需第三方登录或企业 SSO,选对联邦协议也是架构师必修课。

JWT 安全实现要点

绝对不要使用对称密钥 HMAC 直接在前端签发(密钥会泄漏),生产用 RS256/ES256 非对称,公钥公开验证。严格白名单允许算法、用 timingSafeEqual 做 iss/aud 对比防时序攻击,jti 黑名单支持吊销。

import { createSign, createVerify, randomBytes, timingSafeEqual } from "node:crypto";

export interface JwtConfig {
    algorithm: "RS256";
    privateKeyPem: string;
    publicKeyPem: string;
    issuer: string;
    audience: string;
    accessTokenTtlSec: number;
    allowedAlgos: readonly string[];
}
export interface TokenPayload {
    sub: string; scopes: readonly string[]; jti: string;
    exp: number; nbf: number; iat: number; iss: string; aud: string;
}
const B64 = {
    enc: (b: Buffer) => b.toString("base64url"),
    dec: (s: string) => Buffer.from(s, "base64url"),
};
const DENIED = new Set<string>();

export function createJwt(cfg: JwtConfig, claims: Partial<TokenPayload> & { sub: string; scopes: readonly string[] }): string {
    const now = Math.floor(Date.now() / 1000);
    const header = { alg: cfg.algorithm, typ: "JWT", kid: "k1" };
    const payload: TokenPayload = {
        sub: claims.sub, scopes: claims.scopes,
        jti: randomBytes(16).toString("hex"),
        iat: now, nbf: now, exp: now + cfg.accessTokenTtlSec,
        iss: cfg.issuer, aud: cfg.audience,
    };
    const input = `${B64.enc(Buffer.from(JSON.stringify(header)))}.${B64.enc(Buffer.from(JSON.stringify(payload)))}`;
    const s = createSign("RSA-SHA256"); s.update(input);
    return `${input}.${B64.enc(s.sign(cfg.privateKeyPem))}`;
}

export function verifyJwt(cfg: JwtConfig, token: string): TokenPayload {
    const parts = token.split(".");
    if (parts.length !== 3) throw new Error("malformed");
    const [hB64, pB64, sB64] = parts;
    const header = JSON.parse(B64.dec(hB64).toString());
    if (!cfg.allowedAlgos.includes(header.alg) || header.alg === "none") throw new Error("alg not allowed");
    const ver = createVerify("RSA-SHA256"); ver.update(`${hB64}.${pB64}`);
    if (!ver.verify(cfg.publicKeyPem, B64.dec(sB64))) throw new Error("signature mismatch");
    const p = JSON.parse(B64.dec(pB64).toString()) as TokenPayload;
    if (!timingSafeEqual(Buffer.from(p.iss), Buffer.from(cfg.issuer))) throw new Error("iss");
    if (p.aud !== cfg.audience) throw new Error("aud");
    const now = Math.floor(Date.now() / 1000);
    if (p.exp < now) throw new Error("expired");
    if (p.nbf > now) throw new Error("not yet valid");
    if (DENIED.has(p.jti)) throw new Error("revoked");
    return p;
}

OAuth2 / OIDC / SAML 对比

OAuth2 是授权框架不是认证协议,OpenID Connect 在其之上加了 id_token 才是登录。SAML 2.0 是传统企业联邦协议,XML 格式兼容性强但移动端体验差。

特性 OAuth2 + PKCE OIDC (基于OAuth2) SAML 2.0
本质 授权(delegation) 认证(authentication) 认证+授权联邦
适用 移动端/SPA Web/移动/API 企业内部SSO
Token access_token access_token + id_token(JWT) SAML Assertion(XML)
安全性 需PKCE防code注入 原生支持nonce 签名XML流程复杂
移动端体验 好(App转场) 好 差(重定向多)
集成复杂度 中 低 高(双方元数据)

最佳实践

JWT 存敏感信息:短 TTL(5-15min) + refresh_token 轮换。SPA 用 HttpOnly Cookie 承载 refresh_token 避免 XSS。第三方登录场景统一用 OIDC。

X微博Telegram

本文作者

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

评论 (4)

0 / 3000
画画的小鱼
画画的小鱼fishgallery.art2026年9月21日

有个小问题:你文中用的是 @Async 注解,这个默认用的是 SimpleAsyncTaskExecutor,生产环境是不是最好手动配一个线程池?

考研加油鸭
考研加油鸭kaoyan-journey.xyz2026年9月21日

作为一个刚入行的后端新人,这篇文章帮我理清了好多概念,谢谢博主持续输出高质量内容!

代码幽灵
代码幽灵ghostdev.blog2026年9月20日

哈哈,楼主的踩坑经历和我一模一样!我当时就是没注意到这个配置,排查了整整两天,看到这篇文章泪目了。

游戏策划阿哲
游戏策划阿哲2026年9月20日

写得太好了,终于搞懂了分布式事务的几种方案区别,收藏了!

相关文章

GraphQL vs REST:从 7 个维度深度对比

GraphQL vs REST:从 7 个维度深度对比

终结选型焦虑:从网络传输效率、前端开发体验、后端演进成本、缓存策略、类型安全、安全风险、生态工具链 7 大维度系统对比 GraphQL 与 REST,给出清晰决策树与混合架构模式。

1 分钟阅读
Prompt Engineering 入门:Few-Shot + CoT + 结构化输出

Prompt Engineering 入门:Few-Shot + CoT + 结构化输出

系统入门 Prompt Engineering 三大核心技术:Few-Shot 示例学习注入专业领域风格、Chain-of-Thought (CoT) 思维链引导复杂推理、JSON Schema 强制结构化输出对接下游系统。附真实 prompt 模板和避坑指南。

1 分钟阅读
CQRS + Event Sourcing 架构模式解析

CQRS + Event Sourcing 架构模式解析

透彻解析两种高复杂度分布式架构模式:CQRS 读写模型分离实现查询极致性能、Event Sourcing 以事件作为唯一真相源实现全量审计与时间回溯,讨论一致性/快照/幂等难点与反模式。

1 分钟阅读
测试金字塔:单元/集成/E2E 测试比例与落地

测试金字塔:单元/集成/E2E 测试比例与落地

系统解析测试金字塔架构:从底层单元测试(大量快速、Mock 隔离依赖)、中层集成测试(服务/数据库/消息协作真实交互)、顶层 E2E 测试(真实用户路径少量精测)的推荐比例 70% / 20% / 10%,附项目覆盖率指标与落地实践。

1 分钟阅读
快速上手 FastAPI - 构建高性能 REST API

快速上手 FastAPI - 构建高性能 REST API

FastAPI 是现代 Python Web 框架中的佼佼者,基于类型提示自动生成文档、支持异步操作、性能媲美 Node.js。本文将通过实战项目带你从零构建一个完整的 CRUD API,涵盖路由定义、请求验证、依赖注入、数据库集成等核心特性,让你在 30 分钟内掌握 FastAPI 的精髓。

这篇文章需要访问密码 4 分钟阅读
Alembic 深度指南:数据库迁移 + 自动生成 + 分支合并

Alembic 深度指南:数据库迁移 + 自动生成 + 分支合并

SQLAlchemy 官方迁移工具 Alembic 完全指南:从 env.py 配置、autogenerate 自动检测模型变更(字段、索引、约束)、批处理脚本、downgrade 回滚策略,到多人并发开发时 migration 分支冲突、head 分叉合并的标准操作流程,附生产部署检查表。

1 分钟阅读