2、跨站请求伪造CSRF(Cross-site request forgery)
- 含义:跨站点请求伪造。 用户A登录银行网站,登录成功后会设置cookie,黑客诱导用户A登录到黑客的站点,然后会返回一个页面 ,用户访问这个页面时,这个页面会伪造一个转账请求到银行网站。
- 解决办法1 验证码(影响用户体验) 类库(svgCaptcha),刷新的时候后端生成验证码发送给前端,前端保存到session(或者仅仅显示)中,请求的时候带过去(参数),相同服务端就返回,否则就拒绝。
<div class="form-group">
<label for="captcha" id="captcha"></label>
<input id="captcha" class="form-control" placeholder="请输入验证码">
</div>
$.get('/api/captcha').then(data => {
if (data.code == 0) {
$('#captcha').html(data.captcha);
} else {
alert('用户未登录');
location.href = '/login.html';
}
});
var svgCaptcha = require('svg-captcha');
app.get('/api/captcha', function (req, res) {
let session = userSessions[req.cookies.sessionId];
if (session) {
var codeConfig = {
size: 5,// 验证码长度
ignoreChars: '0o1i', // 验证码字符中排除 0o1i
noise: 2, // 干扰线条的数量
height: 44
}
var captcha = svgCaptcha.create(codeConfig);
session.captcha = captcha.text.toLowerCase(); //存session用于验证接口获取文字码
res.send({ code: 0, captcha: captcha.data });
} else {
res.json({ code: 1, data: '没有该用户' });
}
});
let referer = req.headers['referer'];
if (/^https?:\/\/localhost:3000/.test(referer)) {
} else {
res.json({ code: 1, error: 'referer不正确' });
}
- 解决办法3 token验证(推荐)服务端生成token传给浏览器,交互的时候,判断是否相同。token有很多种生成方式,比如cookie或者sessionId,规则前后端双方约定好。 不容易被伪造,一次性的,
function getClientToken() {
let result = document.cookie.match(/token=([^;]+)/);
return result ? result[1] : '';
}
function transfer(event) {
event.preventDefault();
let target = $('#target').val();
let amount = $('#amount').val();
let captcha = $('#captcha').val();
$.post('/api/transfer', {
target,
amount,
captcha,
clientToken: getClientToken()
}).then(data => {
if (data.code == 0) {
alert('转账成功');
location.reload();
} else {
alert('用户未登录');
location.href = '/login.html';
}
});
}
app.post('/api/transfer', function (req, res) {
// let referer = req.headers['referer'];
//if (/^https?:\/\/localhost:3000/.test(referer)) {
let { target, amount, clientToken, captcha } = req.body;
amount = isNaN(amount) ? 0 : Number(amount);
let { username, token } = userSessions[req.cookies.sessionId];
if (username) {
if (clientToken == token) {
let user;
for (let i = 0; i < users.length; i++) {
if (username == users[i].username) {
users[i].money -= amount;
} else if (target == users[i].username) {
users[i].money += amount;
}
}
res.json({ code: 0 });
} else {
res.json({ code: 1, error: '违法操作' });
}
} else {
res.json({ code: 1, error: '用户没有登录' });
}
//} else {
res.json({ code: 1, error: 'referer不正确' });
//}
})