内容简介:跨站请求伪造(CSRF)是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞。Laravel 通过自带的 CSRF 保护中间件让避免应用遭到跨站请求伪造攻击变得简单:Laravel 会自动为每一个被应用管理的有效用户会话生成一个 CSRF “令牌”,然后将该令牌存放在 Session 中,该令牌用于验证授权用户和发起请求者是否是同一个人。
简介
跨站请求伪造(CSRF)是一种通过伪装授权用户的请求来攻击授信网站的恶意漏洞。
Laravel 通过自带的 CSRF 保护中间件让避免应用遭到跨站请求伪造攻击变得简单:Laravel 会自动为每一个被应用管理的有效用户会话生成一个 CSRF “令牌”,然后将该令牌存放在 Session 中,该令牌用于验证授权用户和发起请求者是否是同一个人。
任何时候在 Laravel 应用中定义 HTML 表单,都需要在表单中引入 CSRF 令牌字段,这样 CSRF 保护中间件才能够对请求进行验证。要想生成包含 CSRF 令牌的隐藏输入字段,可以使用 Blade 指令 @csrf
:
<form method="POST" action="/profile"> @csrf ... </form>
中间件组 web
中的中间件 VerifyCsrfToken
会自动为我们验证请求输入的 token 值和 Session 中存储的 token 是否一致,如果没有传递该字段或者传递过来的字段值和 Session 中存储的数值不一致,则会抛出异常。
为了演示该功能,我们在 routes/web.php
中定义一组测试路由:
Route::get('form_without_csrf_token', function (){ return '<form method="POST" action="/hello_from_form"><button type="submit">提交</button></form>'; }); Route::get('form_with_csrf_token', function () { return '<form method="POST" action="/hello_from_form">' . csrf_field() . '<button type="submit">提交</button></form>'; }); Route::get('hello_from_form', function (){ return 'hello laravel!'; });
我们在浏览器中访问 http://blog.test/form_without_csrf_token
并点击页面上的提交按钮时,页面报错,抛出 MethodNotAllowedHttpException
异常,出现这个异常往往就是意味着没有传递 CSRF 令牌字段或者传递的令牌字段不正确:
而当我们访问 http://blog.test/form_csrf_token
并点击页面上的提交按钮时,页面显示正常。
注:CSRF 中间件只只作用于 routes/web.php
中定义的路由,因为该文件下的路由分配了 web
中间件组,而 VerifyCsrfToken
位于 web
中间件组中。
CSRF 令牌 & JavaScript
构建 JavaScript 驱动的应用时,为方便起见,可以让 JavaScript HTTP 库自动在每个请求中添加 CSRF 令牌。默认情况下, resources/js/bootstrap.js
文件会将 csrf-token
meta 标签值注册到 Axios HTTP 库。如果你没有使用这个库,则需要手动在应用中配置该实现。
排除指定 URL 不做 CSRF 安全校验
有时候我们需要从 CSRF 保护中间件中排除一些 URL,例如,如果你使用了第三方支付系统(如支付宝或微信支付)来处理支付并用到他们提供的回调功能,这时候就需要从 Laravel 的 CSRF 保护中间件中排除回调处理器路由,因为第三方支付系统并不知道要传什么 token 值给我们定义的路由。
通常我们需要将这种类型的路由放到文件 routes/web.php
之外,比如 routes/api.php
。不过,如果必须要加到 routes/web.php
中的话,你也可以在 VerifyCsrfToken
中间件中将要排除的 URL 添加到 $except
属性数组:
<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; class VerifyCsrfToken extends Middleware { /** * 从 CSRF 验证中排除的 URL * * @var array */ protected $except = [ 'alipay/*', 'http://example.com/foo/bar', 'http://example.com/foo/*', ]; }
注:运行测试时 CSRF 中间件会自动禁止。
X-CSRF-Token
除了将 CSRF 令牌作为 POST 参数进行验证外,还可以通过设置 X-CSRF-Token
请求头来实现验证, VerifyCsrfToken
中间件会检查 X-CSRF-TOKEN
请求头。实现方式如下,首先创建一个 meta
标签并将令牌保存到该 meta
标签:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后在 js 库(如 jQuery)中添加该令牌到所有请求头,这为基于 AJAX 的请求提供了简单、方便的方式来避免 CSRF 攻击:
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });
注:默认情况下, resources/js/bootstrap.js
文件会将 csrf-token
meta 标签值添加到 Axios HTTP 库,如果你没有使用这个库,则需要手动配置应用的行为。
X-XSRF-Token
Laravel 还会将 CSRF 令牌保存到名为 XSRF-TOKEN
的 Cookie 中,你可以使用该 Cookie 值来设置 X-XSRF-TOKEN
请求头。
一些 JavaScript 框架,比如 Angular 和 Axios,会为你自动进行上述设置,基本上你不太需要手动设置这个值。
最后, VerifyCsrfToken
中间件框架底层实现源码位于 vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php
,感兴趣的同学可以去一窥究竟。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- [ Laravel 5.7 文档 ] 基础组件 —— 日志
- [ Laravel 5.7 文档 ] 基础组件 —— 视图
- [ Laravel 5.7 文档 ] 基础组件 —— 路由
- [ Laravel 5.8 文档 ] 基础组件 —— 路由
- [ Laravel 5.8 文档 ] 基础组件 —— 视图
- [ Laravel 5.7 文档 ] 基础组件 —— 错误处理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Master Switch
Tim Wu / Knopf / 2010-11-2 / USD 27.95
In this age of an open Internet, it is easy to forget that every American information industry, beginning with the telephone, has eventually been taken captive by some ruthless monopoly or cartel. Wit......一起来看看 《The Master Switch》 这本书的介绍吧!