Part6.商业解方奥秘:API 接口鉴权保障方案(6/7)
JSON Web Token 方案详解
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络应用环境中以简短的方式安全地传递信息。JWT 常用于身份验证和信息交换,因其紧凑性和自包含性,广泛应用于现代 Web 应用程序和单页面应用(SPA)中。
JWT 的基本结构
JWT 由三部分组成,每一部分之间用句点(.
)分隔:
-
头部(Header): 通常由两个部分组成:
typ
:令牌类型,一般为 "JWT"。alg
:签名算法,例如HS256
(HMAC SHA-256)或RS256
(RSA SHA-256)。
示例:
{ "alg": "HS256", "typ": "JWT" }
经过 Base64Url 编码后,生成 JWT 头部。
-
载荷(Payload): 载荷中包含声明(claims),声明是关于实体(通常是用户)和其他数据的键值对。常见的声明有:
- 注册声明:包含一些预定义的声明,如
sub
(主题)、exp
(过期时间)、iat
(发行时间)等。 - 公共声明:可定义自己的声明,需避免与其他人冲突。
- 私有声明:自己定义的声明,适用于特定场景。
示例:
{ "sub": "1234567890", "name": "John Doe", "admin": true, "iat": 1516239022 }
载荷同样经过 Base64Url 编码,形成 JWT 的第二部分。
- 注册声明:包含一些预定义的声明,如
-
签名(Signature): 为了生成签名部分,需要将编码后的头部和载荷以及一个密钥,使用指定的算法进行签名。这个过程确保了 JWT 的完整性和真实性。
示例:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret )
JWT 的工作原理
- 用户通过用户名和密码等凭据进行身份验证。
- 服务器验证用户的凭据,生成 JWT,并将其返回给用户。JWT 通过 Base64Url 编码而成。
- 用户存储 JWT,通常存储在浏览器的
localStorage
或sessionStorage
中。 - 用户在每次请求时将 JWT 发送到服务器,通常通过 HTTP 请求的 Authorization 头部。
- 服务器接收到 JWT 后验证其签名与内容。如果有效,服务器执行该请求;如果无效,返回相应的错误信息。
JWT 的优势
- 无状态:JWT 以自包含的方式存储用户信息,服务器不需要存储用户会话信息,适合分布式系统。
- 跨域支持:由于 JWT 是基于标准的字符串格式,可以轻松支持跨域请求。
- 灵活性:可以在 Token 中存储自定义数据,不仅限于身份验证相关的信息。
- 安全性:通过签名算法保证数据的完整性,避免被篡改。
JWT 的缺点
- 不可撤销性:JWT 一旦生成,无法简单地撤销,除非设计了 Token 刷新机制。
- 过期管理:需要合理设置过期时间,过长会带来安全隐患,过短则可能影响用户体验。
- 隐私问题:JWT 中的信息是Base64Url编码的,并未加密,因此敏感信息不应直接放在 Token 中。
常见用例
- 用户身份验证:用户登录成功后,会话管理通过发放 JWT 实现。
- API 访问控制:保护 API 端点,确保只有持有有效 Token 的用户才能访问。
- 单点登录(SSO):多个系统之间共享 JWT,实现单点登录。
总结
JWT 是一种简单、高效且灵活的身份验证和信息交换机制,其无状态和自包含的特点使其成为现代 Web 应用程序中广泛使用的身份认证方案。尽管存在一些缺点,但通过合理的设计和实现,可以充分发挥 JWT 的优势。
jsonwebtoken 模块:API 全解析
jsonwebtoken
是一个流行的 Node.js 模块,用于生成和验证 JSON Web Tokens (JWT)。它提供了简单易用的 API,使得在 Node.js 应用程序中实现 JWT 身份验证变得非常方便。以下是 jsonwebtoken
模块的主要 API 及其使用方法。
安装
首先,你需要通过 npm 安装 jsonwebtoken
模块:
npm install jsonwebtoken
主要 API
1. jwt.sign(payload, secretOrPrivateKey, [options, callback])
生成一个 JWT。
payload
: 要编码到 JWT 中的数据,可以是对象或字符串。secretOrPrivateKey
: 用于签名 JWT 的密钥或私钥。options
: 可选参数,包含以下常用选项:algorithm
(默认:HS256
): 签名算法。expiresIn
: 令牌的过期时间,例如60
、"2 days"
、"10h"
、"7d"
。notBefore
: 令牌生效时间。audience
: 令牌的受众。issuer
: 令牌的发行者。jwtid
: 令牌的唯一标识符。subject
: 令牌的主题。noTimestamp
: 如果为true
,则不包含iat
(issued at) 声明。header
: 自定义 JWT 头部。
callback
: 可选的回调函数,用于异步生成 JWT。
示例:
const jwt = require('jsonwebtoken');
const payload = { userId: 123, name: 'John Doe' };
const secretKey = 'your-secret-key';
// 同步生成 JWT
const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
console.log(token);
// 异步生成 JWT
jwt.sign(payload, secretKey, { expiresIn: '1h' }, (err, token) => {
if (err) throw err;
console.log(token);
});
2. jwt.verify(token, secretOrPublicKey, [options, callback])
验证并解码一个 JWT。
token
: 要验证的 JWT。secretOrPublicKey
: 用于验证 JWT 的密钥或公钥。options
: 可选参数,包含以下常用选项:algorithms
: 允许的签名算法数组。audience
: 验证令牌的受众。issuer
: 验证令牌的发行者。ignoreExpiration
: 如果为true
,则忽略令牌的过期时间。ignoreNotBefore
: 如果为true
,则忽略令牌的生效时间。subject
: 验证令牌的主题。clockTolerance
: 允许的时间偏差,单位为秒。maxAge
: 令牌的最大有效期。clockTimestamp
: 当前时间戳,用于验证令牌的过期时间。
callback
: 可选的回调函数,用于异步验证 JWT。
示例:
const jwt = require('jsonwebtoken');
const token = 'your-jwt-token';
const secretKey = 'your-secret-key';
// 同步验证 JWT
try {
const decoded = jwt.verify(token, secretKey);
console.log(decoded);
} catch (err) {
console.error('Token verification failed:', err.message);
}
// 异步验证 JWT
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
console.error('Token verification failed:', err.message);
return;
}
console.log(decoded);
});
3. jwt.decode(token, [options])
解码一个 JWT,但不进行验证。
token
: 要解码的 JWT。options
: 可选参数,包含以下常用选项:complete
: 如果为true
,则返回包含头部和载荷的对象。json
: 如果为true
,则强制解析载荷为 JSON。
示例:
const jwt = require('jsonwebtoken');
const token = 'your-jwt-token';
// 解码 JWT
const decoded = jwt.decode(token, { complete: true });
console.log(decoded);
示例应用
以下是一个简单的 Express 应用示例,展示了如何使用 jsonwebtoken
进行用户身份验证:
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
const secretKey = 'your-secret-key';
app.use(bodyParser.json());
// 模拟用户数据库
const users = [
{ id: 1, username: 'user1', password: 'password1' },
{ id: 2, username: 'user2', password: 'password2' }
];
// 登录接口
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (!user) {
return res.status(401).json({ message: 'Invalid credentials' });
}
const token = jwt.sign({ userId: user.id }, secretKey, { expiresIn: '1h' });
res.json({ token });
});
// 受保护的接口
app.get('/protected', (req, res) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
return res.status(403).json({ message: 'Failed to authenticate token' });
}
res.json({ message: 'Welcome to the protected route', user: decoded });
});
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
总结
jsonwebtoken
模块提供了简单而强大的 API,使得在 Node.js 应用中实现 JWT 身份验证变得非常容易。通过 jwt.sign
生成 JWT,通过 jwt.verify
验证 JWT,可以有效地保护你的 API 和资源。
JWT 操作:创建、签发、解码与验证
JSON Web Token (JWT) 的创建与签发、解码与验证是 JWT 身份验证流程中的核心步骤。以下是这些步骤的详细说明及其在代码中的实现。
1. JWT 创建与签发
JWT 的创建与签发涉及生成一个包含用户信息的令牌,并使用密钥对其进行签名,以确保数据的完整性和真实性。
使用 jsonwebtoken
模块
在 Node.js 中,可以使用 jsonwebtoken
模块来创建和签发 JWT。
示例代码:
const jwt = require('jsonwebtoken');
// 用户信息
const user = {
id: 123,
username: 'john_doe',
role: 'admin'
};
// 密钥
const secretKey = 'your-secret-key';
// 生成 JWT
const token = jwt.sign(user, secretKey, { expiresIn: '1h' });
console.log('Generated JWT:', token);
代码说明
- 用户信息:定义一个包含用户信息的 JavaScript 对象,这些信息将被编码到 JWT 的载荷部分。
- 密钥:定义一个用于签名的密钥。密钥可以是简单的字符串或复杂的加密密钥。
- 生成 JWT:使用
jwt.sign
方法生成 JWT。该方法接受三个参数:user
:要编码的用户信息。secretKey
:用于签名的密钥。options
:可选参数,例如expiresIn
指定令牌的过期时间。
2. JWT 解码
JWT 解码涉及将 JWT 解析为其原始的头部和载荷部分,但不进行验证。通常用于调试或查看 JWT 的内容。
使用 jsonwebtoken
模块
示例代码:
const jwt = require('jsonwebtoken');
const token = 'your-jwt-token';
// 解码 JWT
const decoded = jwt.decode(token, { complete: true });
console.log('Decoded JWT:', decoded);
代码说明
- JWT 令牌:准备要解码的 JWT 令牌。
- 解码 JWT:使用
jwt.decode
方法解码 JWT。该方法接受两个参数:token
:要解码的 JWT 令牌。options
:可选参数,例如complete
为true
时将返回包含头部和载荷的对象。
3. JWT 验证
JWT 验证涉及检查 JWT 的签名是否有效,以及 JWT 是否在有效期内。验证成功后,可以信任 JWT 中的信息。
使用 jsonwebtoken
模块
示例代码:
const jwt = require('jsonwebtoken');
const token = 'your-jwt-token';
const secretKey = 'your-secret-key';
// 验证 JWT
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
console.error('Token verification failed:', err.message);
return;
}
console.log('Valid JWT:', decoded);
});
代码说明
- JWT 令牌:准备要验证的 JWT 令牌。
- 密钥:准备用于验证的密钥。密钥必须与生成 JWT 时使用的密钥相同。
- 验证 JWT:使用
jwt.verify
方法验证 JWT。该方法接受三个参数:token
:要验证的 JWT 令牌。secretKey
:用于验证的密钥。callback
:回调函数,用于处理验证结果。如果验证失败,回调函数将接收到一个错误;如果验证成功,回调函数将接收到解码后的用户信息。
示例应用
以下是一个完整的示例,展示了如何在 Express 应用中实现 JWT 的创建、签发、解码和验证:
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
const secretKey = 'your-secret-key';
app.use(bodyParser.json());
// 模拟用户数据库
const users = [
{ id: 1, username: 'user1', password: 'password1' },
{ id: 2, username: 'user2', password: 'password2' }
];
// 登录接口
app.post('/login', (req, res) => {
const { username, password } = req.body
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
你是否渴望全面提升前端技能?本专栏将带你畅游前端世界!从 JS 深析趣谈,让你领略 JavaScript 的独特魅力;到前端工程漫话,掌握项目构建精髓。深入洞察框架原理,探索 Node 全栈开发。泛端开发趣闻,开启多端应用新视野;揭秘商业解方奥秘,把握行业趋势。高阶专题层层剖析,助你突破技术瓶颈。更有前端面试指南,为求职保驾护航。无论你是新手小白还是资深开发者,这里都有你需要的知识盛宴!