# CSRF 保護
## 介紹
Laravel 可以輕松地保護你的應用程序免受 「[cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery)」(CSRF)攻擊,跨站點請求偽造是一種惡意攻擊,它憑借已通過身份驗證的用戶身份來運行未經過授權的命令。
Laravel 會自動為每個活躍用戶的會話生成一個 CSRF 「令牌」。該令牌用于驗證經過身份驗證的用戶是否是向應用程序發出請求的用戶。
無論何時,當您在應用程序中定義 HTML 表單時,都應該在表單中包含一個隱藏的 CSRF 標記字段,以便 CSRF 保護中間件可以驗證該請求,您可以使用`@csrf`Blade 指令來生成令牌字段,如下:
~~~php
<form method="POST" action="/profile">
@csrf
...
</form>
~~~
包含在 web 中間件組里的`VerifyCsrfToken`「[中間件](https://laravel-china.org/docs/laravel/5.7/middleware)」會自動驗證請求里的令牌是否與存儲在會話中令牌匹配。
#### CSRF 令牌 & JavaScript
當構建由 JavaScript 驅動的應用時,可以方便地讓 JavaScript HTTP 函數庫發起每一個請求時自動附上 CSRF 令牌。默認情況下,`resources/js/bootstrap.js`文件會用 Axios HTTP 函數庫注冊的`csrf-token`meta 標簽中的值。如果你不使用這個函數庫,你需要手動為你的應用配置此行為。
## CSRF 白名單
有時候你可能希望設置一組并不需要 CSRF 保護的 URL。例如,如果你正在使用「[Stripe](https://stripe.com/)」處理付款并使用了他們的 webhook 系統,你會需要從 CSRF 的保護中排除 Stripe webhook 處理程序路由,因為 Stripe 并不會給你的路由發送 CSRF 令牌。
典型做法,你可以把這類路由放到`routes/web.php`外,因為`RouteServiceProvider`的`web`中間件適用于該文件中的所有路由。不過,你也可以通過將這類 URI 添加到`VerifyCsrfToken`中間件的`$except`屬性來排除對這類路由的 CSRF 保護,如下所示:
~~~php
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* 這些 URI 將免受 CSRF 驗證
*
* @var array
*/
protected $except = [
'stripe/*',
'http://example.com/foo/bar',
'http://example.com/foo/*',
];
}
~~~
> {tip} 當「[運行測試](https://laravel-china.org/docs/laravel/5.7/testing)」時,CSRF 中間件會自動禁用。
## X-CSRF-TOKEN
除了檢查 POST 參數中的 CSRF 令牌外,`VerifyCsrfToken`中間件還會檢查`X-CSRF-TOKEN`請求頭。你應該將令牌保存在 HTML`meta`標簽中,如下:
~~~php
<meta name="csrf-token" content="{{ csrf_token() }}">
~~~
然后,一旦你創建了`meta`標簽,就可以指示像 jQuery 這樣的庫自動將令牌添加到所有請求的頭信息中。還可以為基于 AJAX 的應用提供簡單、方便的 CSRF 保護。如下:
~~~php
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
~~~
> {tip} 默認情況下,`resources/assets/js/bootstrap.js`文件會用 Axios HTTP 函數庫注冊`csrf-token`meta 標簽中的值。如果不使用這個函數庫,則需要為你的應用手動配置此行為。
## X-XSRF-TOKEN
Laravel 將當前的 CSRF 令牌存儲在一個`XSRF-TOKEN`cookie 中,該 cookie 包含在框架生成的每個響應中。你可以使用 cookie 值來設置`X-XSRF-TOKEN`請求頭。
這個 cookie 主要是作為一種方便的方式發送的,因為一些 JavaScript 框架和庫,例如 Angular 和 Axios,會自動將它的值放入`X-XSRF-TOKEN`頭中。