LaravelとAxiosにおけるより良いCSRFリフレッシュ
この記事は使用の文脈で書かれているInertia.js , しかし、概念とコードのスニペットは、あなたが
私は大ファンですInertia.js Laravelを使用したアプリケーションのビルド時.あなたがそれに慣れていないならば、彼らのサイトに行って、それを読んでください.
一般的な問題は、スパのようなアプリケーションを行うときに、慣性を使用するように、あなたはCSRFの不整合の例外に実行されますhere ). 慣性mentions a way ユーザーがフレンドリーな方法で意識するようにするには、まだ私はまだ良いユーザー体験として不足していることがわかります.
ユーザーは、CSRFトークンの概念を持っていないか、またはアプリケーションでいくつかの要求をするために必要です.彼らがアイドル状態になった後に彼らのセッションに戻るならば、トークンは期限切れになります.彼らが何かをして、保存しようとしているとき、「ページが期限切れになった」と言うことはイライラするでしょう、そして、彼らが問題を解決するためにページを更新する必要があるということは非常に直感的でありません.
私は、新しいトークンを作成するために単純なaxiosインターセプターと終点を加えることによって、それがユーザーのために継ぎ目がなくて、まだそのセキュリティ目的に役立つことができるとわかりました.
エンドポイントの追加
まず、新しいトークンを得るためのエンドポイントを追加しましょう.
axiosインターセプターの追加
慣性は、要求をするために使用する人気のライブラリであるinterceptors これにより、レスポンスを引き継ぐ前にレスポンスを「即座に」インターセプトすることができます.
私は、この行動を組織化するのが好きです
我々は、インポートする必要があります
エラーハンドラについては、
エラー応答で、Axiosは初期リクエストを作成するために使用された設定を与えます.基本的には、この点で2つのことをする必要があります. 新しいトークンを 再生トークンを持つ元のリクエストを再試行します. コールバックを作るつもりです
テスト
シンプルを作ろう
ミドルウェアが処理されると、リクエストで渡されたトークンが送信したトークンに一致するかどうかをチェックします. 我々はランダムにトークンを再生成する追加されたスニペット.それが再生されるならば、トークンは一致しません. 彼らがマッチしないとき、それは 私たちのインターセプターは 最終的には、ミドルウェアはトークンを変更せず、要求は正しく解決されます. VUE 3を慣性で使っているので、このリクエストをするためのコンポーネントを作ります.
ボタンをクリックするとコンソールに表示されます.
初めての投稿 次にリクエストを送信する 原作 ボタンを複数回クリックすると、失敗しない場合があります.これはランダムトークンの不一致をシミュレートしているためです.
掃除
テストを終えたら、ミドルウェアの
概要
全体的に、我々のcodebaseへの影響はかなり最小限です、しかし、ユーザー経験は大いに改善されます.ユーザーは自分のセッションを残すことができますし、自分のCSRFトークンを期限切れにすることができます.戻って、要求をすることは彼らの望ましいワークフローを中断しません.
axios
あなたのLaravelプロジェクトのパッケージ.私は大ファンですInertia.js Laravelを使用したアプリケーションのビルド時.あなたがそれに慣れていないならば、彼らのサイトに行って、それを読んでください.
一般的な問題は、スパのようなアプリケーションを行うときに、慣性を使用するように、あなたはCSRFの不整合の例外に実行されますhere ). 慣性mentions a way ユーザーがフレンドリーな方法で意識するようにするには、まだ私はまだ良いユーザー体験として不足していることがわかります.
ユーザーは、CSRFトークンの概念を持っていないか、またはアプリケーションでいくつかの要求をするために必要です.彼らがアイドル状態になった後に彼らのセッションに戻るならば、トークンは期限切れになります.彼らが何かをして、保存しようとしているとき、「ページが期限切れになった」と言うことはイライラするでしょう、そして、彼らが問題を解決するためにページを更新する必要があるということは非常に直感的でありません.
私は、新しいトークンを作成するために単純なaxiosインターセプターと終点を加えることによって、それがユーザーのために継ぎ目がなくて、まだそのセキュリティ目的に役立つことができるとわかりました.
エンドポイントの追加
まず、新しいトークンを得るためのエンドポイントを追加しましょう.
php artisan make:controller RefreshCsrfTokenController --invokable
このコマンドはinvokable (single-action) controller .<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class RefreshCsrfTokenController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
//
}
}
我々は新鮮なトークンを生成するために必要な機能は1行だけです!$request->session()->regenerateToken();
これは、新しいトークンを作成し、私たちのセッションでそれを格納します.新しいトークンを再生した後に、JSON応答を返すことができます.完了したコントローラ関数は以下のようになります.public function __invoke(Request $request)
{
$request->session()->regenerateToken();
return response()->json();
}
最後に、エンドポイントをroutes/web.php
.Route::get('/csrf-token', \App\Http\Controllers\RefreshCsrfTokenController::class);
バックエンドが準備ができたので、フロントエンドを扱いましょう.axiosインターセプターの追加
慣性は、要求をするために使用する人気のライブラリであるinterceptors これにより、レスポンスを引き継ぐ前にレスポンスを「即座に」インターセプトすることができます.
私は、この行動を組織化するのが好きです
plugins
ディレクトリの私のVUEアプリケーションで、メインでそれを含めるapp.js
ファイル.ファイルを作成しましょうresources/js/plugins
呼ばれるhttps.js
.我々は、インポートする必要があります
axios
ライブラリとインターセプターを設定します.// resources/js/plugins/http.js
import axios from 'axios'
axios.interceptors.response.use()
// Add this line in resources/js/app.js
import './plugins/http'
The axios.interceptors.response.use
関数は2つの引き数を受け入れる2xx
ステータスハンドラ)レスポンスハンドラとエラー( non -2xx
ステータスコード)ハンドラ.成功した反応のために、我々は何もする必要はありません.axios.interceptors.response.use(response => response)
これは応答を正常に返します.エラーハンドラについては、
419
, これはlaravelがIlluminate\Session\TokenMismatchException
. 私は使用するつもりですlodash/get
( lodash
我々が望むすべての特性を持っていないかもしれないオブジェクトから変数を得るきれいな方法のために、デフォルトLaravelプロジェクトとともに来ます.import axios from 'axios'
import get from 'lodash/get'
axios.interceptors.response.use(response => response, err => {
const status = get(err, 'response.status')
if (status === 419) {
// Do something
}
return Promise.reject(err)
})
ステータスが419でないならば、我々は通常通り約束を拒絶します.エラー応答で、Axiosは初期リクエストを作成するために使用された設定を与えます.基本的には、この点で2つのことをする必要があります.
/csrf-token
我々が始めにした終点.async
それで、我々は我々を呼ぶことができます/csrf-token
エンドポイントawait
. 完全な実装です.import axios from 'axios'
import get from 'lodash/get'
axios.interceptors.response.use(response => response, async err => {
const status = get(err, 'response.status')
if (status === 419) {
// Refresh our session token
await axios.get('/csrf-token')
// Return a new request using the original request's configuration
return axios(err.response.config)
}
return Promise.reject(err)
})
この時点で、実際には、エンドユーザーのシームレスな体験をするために、2行のコードを追加する必要がありました.テスト
シンプルを作ろう
post
エンドポイント閉鎖機能を使用してください.インroutes/web.php
Route::post('/test', fn () => response()->json(['status' => 'ok']));
今、我々は少し混乱を加える必要がありますapp/Http/Middleware/VerifyCsrfToken.php
期限切れのトークンをシミュレートするミドルウェアデフォルトでは、このミドルウェアはIlluminate\Foundation\Http\Middleware\VerifyCsrfToken
既に機能を含むクラスhandle
関数.チェックする前にトークンを再生することで少し騒乱を起こすことがあります.public function handle($request, Closure $next)
{
if (random_int(0, 1)) {
$request->session()->regenerateToken();
}
return parent::handle($request, $next);
}
The random_int(0, 1)
乱数を生成する0
or 1
, そしてもし1
それから、それは我々のセッションで新しいトークンを生成します.以下に、TokenMismatchException
, ナカ419
ステータスコード./csrf-token
, そしてそれは再びトークンを再生成します.<template>
<button type="button" @click.prevent="sendTest">Test</button>
</template>
<script>
import { defineComponent } from 'vue'
import axios from 'axios'
export default defineComponent({
setup () {
const sendTest = async () => {
const { data } = await axios.post('/test')
console.log(data)
}
return {
sendTest
}
}
})
</script>
クリックするだけで簡単なボタンがpost
我々の要求/test
エンドポイントとログの結果は、この場合は{ "status": "ok" }
私たちの/test
エンドポイント.ボタンをクリックするとコンソールに表示されます.
/test
, それは失敗する419
, これはTokenMismatchException
. /csrf-token
, それは、それが我々の迎撃犯によって捕えられたことを意味します./test
リクエストは再試行され、今回は成功しました(ミドルウェアはリクエストを処理する前にトークンを再生成しませんでした).掃除
テストを終えたら、ミドルウェアの
handle
私たちがLaravelがこの特定のミドルウェアを管理したいので、完全に機能してください.また、削除します/test
ルートroutes/web.php
.概要
全体的に、我々のcodebaseへの影響はかなり最小限です、しかし、ユーザー経験は大いに改善されます.ユーザーは自分のセッションを残すことができますし、自分のCSRFトークンを期限切れにすることができます.戻って、要求をすることは彼らの望ましいワークフローを中断しません.
Reference
この問題について(LaravelとAxiosにおけるより良いCSRFリフレッシュ), 我々は、より多くの情報をここで見つけました https://dev.to/grantholle/better-csrf-refreshing-in-laravel-and-axios-177cテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol