Cross-site request forgery 就是 CSRF ... 跨站请求身份伪造。这是一种功击的方法 ... 就是如果你的网站的用户访问了黑客提供的页面,在这个页面上,黑客可以很容易让用户向你的网站去提交请求,如果你的用户已经登录了你的网站,你的网站一般很难判断这是一次功击,并不是用户自己发出的请求。这就是 CSRF。
防止 CSRF 比较有效的办法就是,去生成一个 token ,放在用户的 session 里面,在要提交的表单上,会有一个隐藏的 token 字段,当用户提交表单的时候,会去比较这两个 token ,如果匹配就正常去执行这个请求,如果不匹配就会放弃。
如果使用 Laravel 的 Form 类的 open 方法去开始一个表单,在表单里面,已经包含了这个隐藏的 token 字段 .. 但是默认情况下,提交表单的时候,不会去对比表单里的 token 还有用户 session 里的 token ..
想要去对比的话,我们需要在路由或者控制器上,去使用 csrf 这个过滤器 ...
先打开 routes.php ,之前已经介绍了怎么样在路由上去应用过滤器 ... 想在这个路由上使用多个过滤器 ... 可以用 竖线分隔一下 ... 再输入一个 csrf ...
Route::get('movies/create', array(
'before' => 'auth|csrf',
'uses' => 'MovieController@create'
));
不过在这个路由上,不能使用 csrf 这个过滤器,因为没有对比的 token 。先去掉它 ...
下面,我们再去看看怎么样在控制器里面使用过滤器 ... 打开 MovieController 这个控制器 ...
在控制器里使用过滤器,可以把过滤器放在构造函数里面 ... 先去创建一个构造函数 .. . public function ... __construct ... 然后使用当前对象的 beforeFilter .. 表示要去添加 before 类型的过滤器 .. 就是在请求之前的过滤器 ...
第一个参数是过滤器的名字 ... 这里我们用一个 csrf ...
第二个参数是这个过滤器应用的范围 ... 它是一个数组 .. 然后输入一个 on ... 表示,把这个过滤器应用到什么地方 ... 它的值设置成 post 竖线 ... put ... delete ...
它的意思就是,把 csrf 这个过滤器,用在使用 post ,put 或者 delete 请求的方法上 ... 基本就是除了 get 方法以外的所有的方法 .. .
public function __construct() {
$this->beforeFilter('csrf', array('on' => 'post|put|delete'));
}
保存 ...
演示
打开电影列表页面 ... 我们可以查看一下这个 删除 按钮元素 ... 注意在这个表单上,有一个隐藏的 token 元素 ... 在点击 删除 的时候 .. 应用在 MovieController 控制器上应用了 csrf 过滤器 .. 所以,提交这个删除请求,就会去比较这里的 token 跟用户 session 里面的 token ...
我们可以修改一下这个 token 的值 ... 然后再点击这个删除按钮 ...
会显示一个错误 ... TokenMismatchException ... token 不匹配的错误 ...
再点击一个没有修改 token 值的删除按钮 ...
token 匹配 ... 就会成功的删除掉这个电影内容 ...