舉例:
想像你的產品有個/user/email route允許post request去修改已經認證過的使用者的email
而這時若沒有CSRF保護, 惡意網站可以創造一個html表單指向你的產品/user/email 且送出惡意的email address
<form action="https://your-application.com/user/email" method="POST">
<input type="email" value="malicious-email@example.com">
</form>
<script>
document.forms[0].submit();
</script>
為了保護這個問題,我們需要檢查所有post、put、patch和delete 請求的secret session值讓惡意的應用無法進入
Laravel 自動生成一個CSRF token給每個session, 這個token用來確認已經認證過的使用者確實就是送請求來的人。因為這個token被存在使用者的session且每次session生成時就會在生成,讓惡意程式無法近來。
至於token 我們可以透過request的session曲的token,或直接call csrf_token()
use Illuminate\Http\Request;
Route::get('/token', function (Request $request) {
$token = $request->session()->token();
$token = csrf_token();
// ...
});
而在我們定義"POST", "PUT", "PATCH", or "DELETE" 在html表單時, 需加上_token這個欄位,為了方便,我們可以用@csrf 替代
<form method="POST" action="/profile">
@csrf
<!-- Equivalent to... -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>
而App\Http\Middleware\VerifyCsrfToken
這隻middleware會幫我們檢查傳進來的token是否跟session裡的token相同
除了在POST當參數,App\Http\Middleware\VerifyCsrfToken也可以用X-CSRF-TOKEN在request header裏
<meta name="csrf-token" content="{{ csrf_token() }}">
接著你可以在jquery裡自動加入X-CSRF-TOKEN到request header裡面
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
好,這樣我了解CSRF保護的重要性了,明天我要來試試看能不能把登入畫面填的值送到程式裡面讓程式能接到這些值。