Masayan tech blog.

  1. ブログ記事一覧>
  2. 【Laravel】CSRF保護の仕組みをざっくり紹介

【Laravel】CSRF保護の仕組みをざっくり紹介

公開日

前置き

本記事では、laravelを学習しはじめの頃に遭遇する419エラーが出る仕組みをざっくり紹介しています。結論から言うと、laravelのフレームワークが、CSRF対策を行ってくれているために、Httpリクエスト時に必要な情報が抜けているとエラーが表示されるという仕組みです。

※全ての処理を書いてしまうと大変なことになるため、処理のポイントとなる部分のみを端折って記載していますので、その点はご了承ください。

※セッションの保存先はデフォルトの"file"という前提で記載しています。

csrfとは

公式Documentから引用

クロスサイトリクエストフォージェリは、認証済みユーザーに代わって不正なコマンドを実行する、悪意のある攻撃の一種です。

全体流れ

ブラウザ

"/"へアクセスしてサーバーへリクエスト

サーバー

40字のランダムな文字列データ(暗号)を生成
※後でこの値とフォームから送られてくる_csrfの値を照合する

/vendor/laravel/framework/src/Illuminate/Session/Store

protected function generateSessionId()
{
  return Str::random(40);
}

暗号の値をセッションへ保存

/storage/framework/sessions/ へ暗号の値をファイルとして保存する(ファイル名が暗号の値)

/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem

public function put($path, $contents, $lock = false)
{
  return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
}

暗号の値を読み取る

/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem

public function sharedGet($path)
{
$contents = '';

$handle = fopen($path, 'rb');

if ($handle) {
  try {
    if (flock($handle, LOCK_SH)) {
      clearstatcache(true, $path);
      $contents = fread($handle, $this->size($path) ?: 1);
      flock($handle, LOCK_UN);
    }
  } finally {
    fclose($handle);
  }
}

return $contents;
}

htmlの<form>内の<input name= “_token”>のvalueにセット

ブラウザ

リクエストを投げる(/loginへのPOST)

サーバー

formから送られてきたcsrfの値とサーバー側の値が等しいかチェック

/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken

protected function tokensMatch($request)
{
  $token = $this->getTokenFromRequest($request);
  return is_string($request->session()->token()) &&
  is_string($token) &&
  hash_equals($request->session()->token(), $token);
}

チェックが完了したら、レスポンスヘッダーに、Cookieをセットしてブラウザに返す。

まとめ

いかがでしたでしょうか。本記事では、laravelを学習しはじめの頃に遭遇する419エラーが出る仕組みをざっくり紹介しています。結論から言うと、laravelのフレームワークが、CSRF対策を行ってくれているために、Httpリクエスト時に必要な情報が抜けているとエラーが表示されるという仕組みです。