定义

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_urlrequest.origin的比拟。
这里base_url指的是这次申请的domain地址,origin指的是这个申请是从哪里来的。
请看上面的例子:
假如咱们在站点Bhttps://websiteb.com触发了一个到站点Ahttps://websitea.com的申请:
POST https://websitea.com/path
那么此时在A的server:
request.base_urlhttps://websitea.com
request.originhttps://websiteb.com