防重放攻击实战总结:从前端到后端的全面防护策略
优化前:卡得不行
最近在做一个项目,涉及到一些敏感的API调用,比如用户登录、支付等。一开始我们没太注意防重放攻击这块,结果上线后发现性能问题严重,特别是高峰期,页面加载时间长到让人抓狂。用户反馈说,有时候登录页面都要等个十几秒才能打开,支付流程更是卡得不行。
找到病颈了!
发现问题后,我们首先使用了一些常见的性能分析工具,比如Chrome DevTools和Lighthouse。通过这些工具,我们发现了很多请求都在重复发送,导致服务器压力大增,响应时间也变长。特别是登录和支付接口,由于没有防重放机制,每次刷新页面都会重新发起请求,造成了严重的性能瓶颈。
优化后:流畅多了
试了几种方案,最后这个效果最好。我们在客户端和服务器端都做了相应的优化。
客户端优化
在客户端,我们主要做了以下几点优化:
- 增加请求缓存:对于一些不频繁变化的数据,我们增加了本地缓存机制,避免每次都从服务器获取。
- 使用nonce值:在每个请求中加入一个随机的nonce值,并在服务器端进行验证,确保每个请求都是唯一的。
- 减少不必要的请求:对一些不需要实时更新的数据,我们改为定时拉取,而不是每次操作都重新请求。
以下是优化前后的代码对比:
优化前的代码
function login(username, password) {
fetch('https://jztheme.com/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username, password })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
}
优化后的代码
let nonce = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
function login(username, password) {
fetch('https://jztheme.com/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username, password, nonce })
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
localStorage.setItem('user', JSON.stringify(data.user));
}
console.log(data);
})
.catch(error => console.error('Error:', error));
}
// 缓存登录状态
if (localStorage.getItem('user')) {
const user = JSON.parse(localStorage.getItem('user'));
// 如果用户已经登录,直接跳转到首页
window.location.href = '/dashboard';
}
服务器端优化
在服务器端,我们也做了一些调整:
- 增加nonce校验:在服务器端对每个请求中的nonce值进行校验,确保其唯一性。
- 增加时间戳校验:在请求中加入时间戳,并在服务器端进行时间戳校验,防止重放攻击。
以下是服务器端的示例代码:
服务器端优化前的代码
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
// 验证用户名和密码
if (username === 'admin' && password === 'password') {
res.json({ status: 'success', user: { id: 1, name: 'Admin' } });
} else {
res.status(401).json({ status: 'failure', message: 'Invalid credentials' });
}
});
服务器端优化后的代码
const nonces = new Set();
app.post('/api/login', (req, res) => {
const { username, password, nonce, timestamp } = req.body;
// 校验nonce值
if (nonces.has(nonce)) {
return res.status(400).json({ status: 'failure', message: 'Nonce already used' });
}
nonces.add(nonce);
// 校验时间戳
const now = Date.now();
if (Math.abs(now - timestamp) > 60000) {
return res.status(400).json({ status: 'failure', message: 'Timestamp is invalid' });
}
// 验证用户名和密码
if (username === 'admin' && password === 'password') {
res.json({ status: 'success', user: { id: 1, name: 'Admin' } });
} else {
res.status(401).json({ status: 'failure', message: 'Invalid credentials' });
}
});
性能数据对比
优化前,登录页面的平均加载时间是10-15秒,支付流程更是高达20秒左右。优化后,登录页面的加载时间降到了800毫秒左右,支付流程也缩短到了1.5秒左右。用户的反馈也明显好转,再也没有抱怨页面卡顿的问题了。
以上是我的优化经验,有更好的方案欢迎交流
这次优化虽然解决了大部分问题,但还有一些小细节需要继续打磨。比如nonce值的存储和清理机制,以及如何更高效地处理时间戳校验。如果有更好的方案或者踩过的坑,欢迎大家在评论区交流。
本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。

暂无评论