token 如何存放才能避免 csrf 攻击

156 天前
 NoKey
放 cookie 中,但是后端不读 cookie
所有请求需要前端把 token 放到 header 中一个参数下
后端读 header 中的这个参数
这样是不是就可以放置 csrf 攻击了呢?
第三方直接通过服务链接带 cookie 过来,因为后端不读取,所以鉴权不通过
2527 次点击
所在节点    程序员
13 条回复
zzNucker
156 天前
存 cookie, header, html 都可以
ss098
156 天前
你是不是在找 OAuth 2.0 Bearer token ?
yinmin
156 天前
常见这 2 种方式吧:
方式一:csrf token 放服务器的 session ,然后前端传 token (header 、post 参数、get 参数都可以)做对比
方式二:csrf token 放 cookie 里(设置成 httponly 和 secure),然后前端传 token (header 、post 参数、get 参数都可以)做对比

方式一的服务器 session 容易丢失,我是推荐方式二,可以做成无服务器状态模式。
happyxhw101
156 天前
一般放在 header 里面可以防止 csrf 攻击,
如果是放在 cookie 里面,那需要单独生成一个 csrf token ,前端用 js 把 csrf token 放在 header 里面,同时生成一个值是 csrf token 的 cookie ,后端收到请求比较 header 和 cookie 里面的值,这种也是常规手段,但也不能做到 100%
happyxhw101
156 天前
Belmode
156 天前
我觉得 CSRF 无非是避免浏览器,在非法跨站请求携带默认参数时,导致的权限问题。那`认证信息`放哪都无所谓了,放 cookie 也可以,放本地存储也可以,提交的时候放 header 也行,放 cookie 也行。只要保证存储和使用时有标记不一样,并且服务端只认带这个标记的`认证信息`。

楼上说的,Bearer Token 就是。`认证信息`存任何地方都行,但是放在请求头上时,Authorization: Bearer <token>。这样就确保,是自己站点的页面执行了 js 发送的请求,不是跨站请求。

所以用 OAuth2.0 之类的认证方式,只要提交请求认证信息时做点不一样的操作,都不用特别考虑 CSRF 攻击,因为从机制上已经避免了。
Belmode
156 天前
@Belmode OP 提问中的疑问的答案是肯定的。你那样操作,是可以避免 CSRF 攻击的。
moon548834
155 天前
@Belmode 请教下为什么 token 放 cookie 里可以呢?我理解 header 是 ok 的
用户 A 请求正常网站 C ,假设用户点了某个钓鱼网站 B ,那么 B->C 的过程不是会把 cookie 信息自动带上吗?

或者说一个普通的 access_token 放到 cookie 面临的问题不能被一个也在 cookie 中的 csrf token 解决?
forvvvv123
155 天前
@happyxhw101

OP 用这个方法就行,最简单实用的,cookie 双重认证, 你所有的重要请求都在页面上用 js 发 post , 发的时候把 cookie 里面的 token 值带到请求上,放 post 参数、header 里都行;

你后端收请求的时候:
1. 先看 cookie 里面有没有 token ,没 token 就拒绝,然后 set-cookie 种个随机数 token ;
2. 再看请求里面带没带和 cookie 一样的 token ,不一样就拒绝;

对 csrf 的问题就解决了;


网上有很多会结合 xss 和 csrf 考虑的,我个人认为这样复杂了,一般有了 xss 漏洞就不考虑 csrf 了,xss 能做的太多了;有 xss 的问题修 xss 的问题,讨论 csrf 都是要在没 xss 没钓鱼的情况下讨论,不然说不清;
Belmode
154 天前
@moon548834 #8

首先,我说以下一般实现,现在很多网站或者说产品,都没有专门设置 CSRF token 的,都不是通过这种手段来避免跨站攻击。
在你例子中,用户从钓鱼网站 B 触发的网站 C 的请求,携带了 Cookie 到目标服务器,但是服务器是不会认可`此次请求已被授权的`,因为不是从网站 C 页面上发起的,所以网站 C 的 JS 没有执行,没有讲 Cookie 中的 token 部分提取出来,放到 Header 中,并拼上`Bearer`之类的符号,所以这次请求,就和用户第一次访问网站 C 一样,是安全的。

这其中关键在于,网站 C 服务端,不认可从其他网页发起的 http 请求,只认可自己页面的,所以借助 Ouath2.0 令牌模式的机制,避免了 CSRF 。

当然你自定义任何方式都可以,只要类似我#6 的说法。

PS1: 理论上令牌可以放到任何位置,但是一般放到 localStorage 里,因为浏览器请求在没有 JS 处理的情况下,不会携带这些信息,有一定安全性。
PS2: 我说的只是一种最简单的模型理论,实际上企业中,预防 CSRF 的手段特别多,因为用户信息和权限的校验步骤非常多,也非常复杂,不是那一种方式就能完成的,都是多种手段并用。
PS3:V 站用了 CSRF token ,并且这个 token 有实效,过期了,页面都直接时效了,可以参考。
moon548834
153 天前
"在你例子中,用户从钓鱼网站 B 触发的网站 C 的请求,携带了 Cookie 到目标服务器,但是服务器是不会认可`此次请求已被授权的`,因为不是从网站 C 页面上发起的"

这个你说的是同源检查吧,如果 C 不做同源检查,那应该是认可的..

ref: https://tech.meituan.com/2018/10/11/fe-security-csrf.html
NoKey
153 天前
@moon548834 后端不仅仅通过 cookie 里面的 token 进行鉴权相关识别,是不是就没问题了,不用管是不是同源?
moon548834
149 天前
@NoKey 应该是吧,总之我还是认为把 token 放 header 里是最佳实践

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1059544

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX