第三方用户派发签名
为了实现你描述的场景,我们需要为第三方用户提供一种方法来创建请求签名,并在 Node.js 服务端验证该签名。以下是详细步骤,包括如何将 URL 和请求参数拼接成字符串进行签名,以及如何在服务器上验证这些签名。
项目设置
首先,确保你已经初始化了一个 npm 项目并安装了 Express:
npm init -y
npm install express创建 API 服务
下面是 Node.js 代码示例,它展示了如何通过 SHA-256 验证 GET 和 POST 请求中的签名:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// 定义密钥用于签名
const SECRET_KEY = 'your_secret_key';
// 用于生成签名的函数
function generateSignature(data) {
return crypto.createHmac('sha256', SECRET_KEY).update(data).digest('hex');
}
// 拼接 URL 和请求参数生成待签名的字符串
function createSignString(method, url, params) {
const sortedParams = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&');
return `${method.toUpperCase()}|${url}|${sortedParams}`;
}
// 中间件:验证签名
function verifySignature(req, res, next) {
const { signature } = req.query || req.body;
const method = req.method;
const url = req.originalUrl.split('?')[0]; // 去除查询参数
const params = method === 'GET' ? req.query : req.body;
if (!signature) {
return res.status(400).json({ error: 'Missing signature' });
}
// 创建签名字符串
const signString = createSignString(method, url, params);
// 生成期望的签名
const expectedSignature = generateSignature(signString);
if (expectedSignature !== signature) {
return res.status(403).json({ error: 'Invalid signature' });
}
next();
}
// 路由:受保护的 API 请求路径
app.use('/api/protected', verifySignature);
app.get('/api/protected', (req, res) => {
res.json({ message: 'GET request signature verified successfully!' });
});
app.post('/api/protected', (req, res) => {
res.json({ message: 'POST request signature verified successfully!' });
});
// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});客户端请求示例
以下是一个生成签名并发送请求的客户端示例:
const crypto = require('crypto');
// 用于生成签名的密钥
const SECRET_KEY = 'your_secret_key';
// 签名生成函数
function generateSignature(data) {
return crypto.createHmac('sha256', SECRET_KEY).update(data).digest('hex');
}
// 创建签名字符串
function createSignString(method, url, params) {
const sortedParams = Object.keys(params).sort().map(key => `${key}=${params[key]}`).join('&');
return `${method.toUpperCase()}|${url}|${sortedParams}`;
}
// 示例 GET 请求
function sendGetRequest() {
const url = '/api/protected';
const params = { param1: 'value1', param2: 'value2' };
const signString = createSignString('GET', url, params);
const signature = generateSignature(signString);
const queryParams = new URLSearchParams({ ...params, signature }).toString();
fetch(`http://localhost:3000${url}?${queryParams}`)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
}
// 示例 POST 请求
function sendPostRequest() {
const url = '/api/protected';
const params = { param3: 'value3', param4: 'value4' };
const signString = createSignString('POST', url, params);
const signature = generateSignature(signString);
fetch(`http://localhost:3000${url}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...params, signature })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
}
sendGetRequest();
sendPostRequest();流程说明
签名生成: 在客户端,将请求的方法、URL 和参数以预定义的格式拼接成字符串,然后通过 SHA-256 和共享密钥生成签名。
签名验证: 在服务器端,接收请求后,提取相同的信息,生成期望的签名,并与客户端提供的签名进行比较。
重要提示: 确保使用 HTTPS 以保护传输中的敏感信息和签名,并保障 SECRET_KEY 的安全性。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Alvin
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果