CSRF跨站请求伪造
CSRF意为跨站请求伪造。
指攻击者盗用了你的身份,以你的名义发送恶意请求。
比如:盗用你的身份购买商品,虚拟货币转账。
那么怎么解决这种漏洞呢?
CSRF防护
思路:
1、在请求转账的时候,服务器响应转账页面,在cookie中设置一个csrf_token值(随机48位字符串)
2、客户端在进行post请求的时候,在请求头中带上自定义的属性'X-CSRFToken',值为cookie中的csrf_token值。
3、服务器在接收到post请求的时候,首先验证响应头中的X-CSRFToken值,和cookies中的csrf_token是不是一致,如果不一致,结束响应。
防护过程:
1、安装cookie-parser
2、生成n位随机字符串:
function getRandomString(n){
var str="";
while(str.length<n){
str+=Math.random().toString(36).substr(2);
}
return str.substr(str.length-n)
}
getRandomString(48); // 调用生成csrf_token
get请求转账页面的时候,在cookie中设置一个csrf_token值(随机48位):
if(req.method=="GET"){
// 渲染转账页面的时候,同时在cookie中设置csrf_token
//设置cookie和session
let csrf_token = getRandomString(48);
res.cookie('csrf_token', csrf_token);
res.render('temp_transfer');
}
接下来,在前端页面中,发起post请求的时候带上自定义的属性'X-CSRFToken',值为cookie中的csrf_token值:
$.ajax({
url:'/transfer',
type:'post',
data:JSON.stringify(params),
contentType:'application/json',
headers:{'X-CSRFToken':getCookie('csrf_token')},
success: function (resp) {
....
}
})
....
function getCookie(name) { //获取cookie的函数
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
最后回到服务器端,处理post请求的时候,判断响应头中得到X-CSRFToken值,和cookie中的csrf_token是不是一致,不一致则取消响应。
else if(req.method=="POST"){
// 判断响应头中的x-csrftoken值,和cookies中的csrf_token进行对比
console.log(req.headers["x-csrftoken"]);
console.log(req.cookies["csrf_token"]);
if((req.headers["x-csrftoken"] === req.cookies["csrf_token"])){
console.log("csrf验证通过!");
}else{
res.send("csrf验证不通过!");
return
}
// 以下可以开始正常处理post请求
}
对每一个POST请求都设置CSRF防护
在app.js文件中可以这么写:
const router = express.Router();
router.all('/', (req, res) => {
if(req.method=="GET"){
res.render('temp_login')
}
...
});
router.all('/transfer', (req, res) => {
...
else if(req.method=="POST"){
let {to_account, money} = req.body;
console.log(to_account, money);
//执行转账功能: ....此处省略
console.log("假装执行转账操作,将当前登录用户的钱转账到指定账户");
console.log(`已经完成转账${money}元到账户${to_account}`);
res.json({to_account,money});
}
});
function csrfProtect(req, res, next){
let method = req.method
if(method=="GET"){
let csrf_token = getRandomString(48);
res.cookie('csrf_token', csrf_token);
next() //执行跳转到下一个函数执行,即app.use(beforeReq,router)中的下一个
}else if(method=="POST"){
// 判断响应头中的x-csrftoken值,和cookies中的csrf_token进行对比
console.log(req.headers["x-csrftoken"]);
console.log(req.cookies["csrf_token"]);
if((req.headers["x-csrftoken"] === req.cookies["csrf_token"])){
console.log("csrf验证通过!");
next()
}else{
res.send("csrf验证不通过!!");
return
}
}
}
app.use(csrfProtect,router)
到这里,我们node.js的基础就结束了,下一篇我会写node项目的搭建过程!