CSRF
Cross Site Request Forgy
跨站请求伪造
需要条件
- 用户登录 A 网站
- A 网站确认身份
- B 网站页面向 A 网站发起请求(带 A 网站身份)
CRSF 攻击危害
- 利用用户登录态---盗取用户资金(转账,消费)
- 用户不知情---冒充用户发帖背锅
- 完成业务请求---损坏网站名誉
- ...
CSRF 攻击防御
过程:
- B 网站向 A 网站请求
- 带 A 网站 Cookies
- 不访问 A 网站的前端
- referer 为 B 网站(这里的 referer 为为数不多的错误单词)
禁止第三方网站带 Cookies,为 Cookies 设置 Same-site 属性
koa 设置方式
ctx.cookies.set("userId", user.id, { httpOnly: false, sameSite: "strict" });
这种方法较好但是,有些浏览器不支持,但将来应该会的
- 不访问 A 网站的前端
- 在前端页面加入验证消息
- 验证码
- 安装第三方插件生成验证码
- 运行
npm install ccap --save
captcha.captcha = async function(ctx, next) { var ccap = require("ccap"); var capt = ccap(); var data = capt.get(); captcha.setCache(ctx.cookies.get("userId"), data[0]); ctx.body = data[1]; }; // 设置 captcha.setCache = function(uid, data) { console.log(uid, dtat); cache[uid] = data; }; //验证 capthcha.validCache = function(uid, dtat) { return cache[uid] === data; };
下面调用上面
console.log(data.captcha); //没有验证码 if (!data.captch) { throw new Erroe("验证码错误"); } //验证码不匹配 var captcha = require("../tools/captcha"); var result = captcha.validCache(ctx.cookies.get("userID"), data.captcha); console.log("result", result); if (!result) { throw new error("验证码错误"); }
- 不访问 A 网站的前端
- 在前端页面加入验证消息
- token
验证码有时是会影响用户体验的,所以就有了 taken,一般为隐藏的文本框
var csrfToken = parseInt(Math.random() * 99999999, 10); ctx.cookies.set("csrfToken", csrfToken); //渲染时 ctx.render("post", { post, comments, csrfToken });
验证
if (!data.crsfToken) { throw new Error("CSRF Token 为空"); } if (data.csrfToken !== ctx.cookies.get("csrfToken")) { throw new Erroe("CSRF Token错误"); }
ajax 做法
html 头部
<meta http-equiv="X-UA-Compatible" content="csrfToken" name="csrf_token" />
referer 为 B 网站
- 验证 referer
- 禁止来自第三方网站的请求
var referer = ctx.request.header.referer; // console.log(ctx.request.header, referer); if(!^https?:\/\/loaclhost/.test(referer)){ // if(referer.indexOf('localhost')===-1)//验证不全面,所以要采用上面的做法 throw new Error('非法请求') }
来源:https://www.cnblogs.com/ygjzs/p/12243504.html