定义
CSRF:cross-site request forgery(跨站点申请伪造)
导致的起因
这要从 Cookie 的作用来讲起。咱们晓得 HTTP 申请是无状态的,然而在理论的 web 利用中,咱们须要申请是有状态的,比方咱们须要记住登录的状态,不必每一个申请都从新登录。想要实现这样的需要咱们就须要 Cookie。
Cookie 在服务器端通过 Set-Cookie
来设置须要存储在 Cookie 的值,而后存储在客户端(浏览器)。之后在客户端发动的任何指向同一个 domain 的申请中,都会带上这些 Cookie 的信息。
那么问题就来了,这里只有是针对同一个 domain 的申请都会带上 cookie,然而并不限度这些申请是从哪里发动的。
咱们来看看上面的场景:
至此,咱们应该对 CSRF Token 有了一个清晰的理解。
在 Rails 中怎么避免
在 Rails 中,避免这种攻打的办法,就是在任何非 GET 的申请中,都要验证一个 authenticity token. 这个 token 对应到每一个 session,每次生成 session 的时候就随机产生一个 token,并存储在 session 中。当向服务器发送申请(非 GET)的时候须要带上这个 token。
那么问题是前端代码发送申请的时如何获取这个 token 呢?
在 Rails 中,如果你是应用 form helper 的话,在后端 render 的时候,会从 session 中去读取这个 token 并插入到 form 的 hidden field 中。如果你是通过 FE JS 发送 ajax 申请的话,你须要从本站的 layout 的 meta tag 中去读区这个 token。
所以对于在第三方站点(B 站)上的申请来讲,它是得不到这个 token 的(如果他曾经能失去这个 token,阐明他曾经有了 session,也就没必要再通过 B 站来发申请了),所以这个申请在服务器端将会无奈通过验证。
补充信息:
Rails 在比拟 token 是否统一的时候,有一个对 request.base_url
和 request.origin
的比拟。
这里 base_url 指的是这次申请的 domain 地址,origin 指的是这个申请是从哪里来的。
请看上面的例子:
假如咱们在站点 B https://websiteb.com
触发了一个到站点 A https://websitea.com
的申请:POST https://websitea.com/path
那么此时在 A 的 server:request.base_url
是 https://websitea.com
request.origin
是 https://websiteb.com