外观
前端接口请求签名指南
这是什么?
想象一下,就像你在快递单上签名一样,我们需要给每个接口请求添加一个"数字签名"。这个签名可以:
- ✅ 证明请求确实来自合法用户
- ✅ 确保数据在传输过程中没有被篡改
- ✅ 防止黑客伪造请求
这个功能特别适合那些不需要登录就能访问的接口。
📝 如何实现签名?
第一步:准备签名工具
首先,我们需要创建一个sign.js
文件来处理签名:
javascript
// 1. 引入必要的工具
import config from '@/config/index.js'
import CryptoJS from 'crypto-js' // 记得先安装这个加密库
// 2. 处理签名参数
export function getSignAllMap(path, json, signJson) {
// 把复杂的数据结构转换成简单的键值对
if (null != json) {
let type = Object.prototype.toString.call(json);
if (type == "[object Object]") {
// 处理对象
for (let key in json) {
let value = json[key];
if (null != value && undefined != value) {
let type2 = Object.prototype.toString.call(value);
let path2 = key;
if (path) {
path2 = path + "." + key;
}
if (type2 == "[object Object]") {
getSignAllMap(path2, value, signJson)
} else if (type2 == "[object Array]") {
for (let i = 0; i < value.length; i++) {
getSignAllMap(path2 + "[" + i + "]", value[i], signJson)
}
} else {
signJson[path2] = value;
}
}
}
} else if (type == "[object Array]") {
// 处理数组
for (let i = 0; i < json.length; i++) {
getSignAllMap(path + "[" + i + "]", json[i], signJson)
}
} else {
signJson[path] = json;
}
}
}
// 3. 生成签名字符串
export function getSignStr(json) {
let signJson = {};
getSignAllMap("", json, signJson)
// 获取所有参数名并排序
let keys = Object.keys(signJson).sort();
// 拼接参数
let signStr = keys.map(key =>
key + "=" + signJson[key]
).join("&");
return signStr;
}
// 4. 生成随机字符串(防止重放攻击)
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// 5. 获取最终签名
export function getSign(url, data) {
// 复制原始数据
let sinData = JSON.parse(JSON.stringify(data))
// 添加签名必要信息
let randomStr = guid(); // 随机字符串
let timestamp = +new Date(); // 当前时间戳
sinData.appId = config.appId; // 应用ID
sinData.appSecret = config.appSecret; // 应用密钥
sinData.randomStr = randomStr; // 随机字符串
sinData.timestamp = timestamp; // 时间戳
// 生成签名字符串并计算签名
let signStr = getSignStr(sinData);
console.log('签名字符串:', signStr);
let sign = CryptoJS.SHA1(signStr).toString();
// 返回带签名的URL
return `${url}?appId=${config.appId}&randomStr=${randomStr}×tamp=${timestamp}&sign=${sign}`
}
第二步:配置应用信息
创建config.js
文件,设置应用信息:
javascript
export default {
appId: 'test', // 你的应用ID
appSecret: '11e1ebfd58254b84a6f3c1d81d27a562', // 你的应用密钥
}
第三步:在代码中使用
javascript
// 1. 引入签名工具
import { getSign } from './sign.js'
// 2. 准备要发送的数据
let data = {
"accountNo": "admin",
"password": "123456"
};
// 3. 获取带签名的URL
let signUrl = getSign(url, data);
// 4. 发送请求
axios.post(signUrl, data)
.then(response => {
console.log('请求成功:', response);
})
.catch(error => {
console.error('请求失败:', error);
});
第四步:配置服务器
在服务器配置文件中添加签名验证规则:
yaml
wueasy:
gateway:
filter:
merchant:
enabled: true # 启用签名验证
items:
- app-id: test # 应用ID
app-secret: 11e1ebfd58254b84a6f3c1d81d27a562 # 应用密钥
name: 测试应用 # 应用名称
time-verify: true # 检查请求时间是否有效
time-interval: PT30M # 请求30分钟内有效
one-verify: true # 防止重复请求
one-time-interval: PT1H # 签名1小时内有效
sign-type: ALL # 签名方式
urls: # 需要验证签名的接口
- /demo/login
💡 工作原理
签名是如何生成的?
📦 收集数据
- 业务数据(如用户名密码)
- 应用信息(appId)
- 时间戳(防止重放)
- 随机字符串(防止重复)
🔄 处理数据
- 将所有数据转换为键值对
- 按键名排序
- 拼接成字符串
🔐 计算签名
- 使用SHA1算法计算签名
- 将签名添加到URL中
服务器如何验证?
⏰ 时间检查
- 验证请求是否在有效期内
- 默认30分钟内有效
🔍 重复检查
- 验证是否是重复请求
- 使用随机字符串防重放
✅ 签名验证
- 使用相同方法计算签名
- 比对签名是否一致
❓ 常见问题
1. 签名验证失败?
- ✓ 检查appId和appSecret是否正确
- ✓ 确认系统时间是否准确
- ✓ 验证参数排序是否正确
- ✓ 打印签名字符串进行对比
2. 请求被拒绝?
- ✓ 检查请求是否超时
- ✓ 确认是否重复请求
- ✓ 验证URL是否正确配置
3. 开发调试问题?
- ✓ 打开详细日志
- ✓ 打印签名参数
- ✓ 使用调试工具跟踪
🎯 最佳实践
开发环境
👨💻 调试建议
- 打印签名字符串
- 关闭时间验证
- 使用固定测试数据
🔧 配置建议
- 延长请求有效期
- 简化签名参数
- 开启详细日志
生产环境
🛡️ 安全建议
- 定期更换密钥
- 启用所有验证
- 使用HTTPS传输
📊 监控建议
- 记录签名失败日志
- 监控异常请求
- 定期检查安全性
🆘 需要帮助?
如果遇到问题,可以:
- 📝 查看日志文件
- 🔍 打印签名参数
- 🌐 检查网络请求
- 📋 验证配置正确
- 💬 联系技术支持