[Laravel] 特定サイト (URI)からのアクセスのみCSRF チェックを除外したい
Laravel の CSRF 対策機能
Laravel には CSRF(クロス・サイト・リクエスト・フォージェリ)対策の機能が備わっています。
1 2 3 4 5 6 |
<form method="POST" action="/hoge"> @csrf ... </form> |
詳しくは CSRF保護 6.x Laravel を見てください。
特定サイトからのアクセスを除外したい
しかし、システム連携などの都合で、特定サイト(URL)からのアクセスについては CSRF のチェックをしないようにしたい場合があります。
上記の CSRF保護 6.x Laravel (URIの除外) の例を見ると VerifyCsrfToken ミドルウェアに
12345678910111213 class VerifyCsrfToken extends Middleware{/*** CSRFバリデーションから除外するURI** @var array*/protected $except = ['stripe/*','http://example.com/foo/bar','http://example.com/foo/*',];}
と書く例が載っているので、ここにリファラーとして除外したいサイトを記載すれば良さそうに思えます。ところがうまくいきません。
なぜなら $except
で指定する除外するURI とは、POST先の URL の(参照される側の)であり、参照元の URL ではないからです。
リファラーを参照して $except を変更する
では、リファラーの URL を使う方法はないのかというと、VerifyCsrfToken ミドルウェアで handle をオーバーライドすれば可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace App\Http\Middleware; use Closure; class VerifyCsrfToken extends Middleware ... /** * 特定のリファラーの場合に、特定ページの CSRF チェックを迂回するために handle をオーバーライドする */ public function handle($request, Closure $next) { // リクエストが特定 URI から始まるものであれば if (\Str::startsWith($request->headers->get('referer'), 'https://example.net/')) { // いくつかの画面では CSRF チェックをしないようにする (配列への追加) $this->except = array_merge($this->except, ['/posts', '/comments']); } return parent::handle($request, $next); } |
これで https://example.net/ から始まる URI がリファラーにセットされているときは、/posts と /comments については CSRF チェックの除外対象とするようになります。
http → https ではリファラーが取れないので注意
通常、 Web ブラウザは、http の URL から https の URL に遷移するときはにリファラーを送出しません。
これは Laravel に限った話ではありません。リファラーを使った処理をするときには注意が必要です。特に開発やテストで http のローカル環境から https のサイトに POST してもリファラーが取れませんので気をつけてください。
参考
ITエンジニア募集中!
キュアコード株式会社はITエンジニアを募集しております。少人数の職場なので、上流・下流やサーバー・クライアント対応の垣根なく、あなたの強みを活かしながら いろいろなことにチャレンジ可能です。エンジニアとしての未経験の方、経験が少ない方も歓迎しています。
下記よりITエンジニア募集の採用情報をご覧いただけます。