CSRF 保護

發送請求

當透過 Inertia 或 Axios 發送請求時,Laravel 會自動包含正確的 CSRF 令牌。但是,如果您使用 Laravel,請務必從您的專案中省略 csrf-token meta 標籤,因為這會阻止 CSRF 令牌正確刷新。

如果您的伺服器端框架包含跨站請求偽造 (CSRF) 保護,您需要確保每個 Inertia 請求都包含必要的 CSRF 令牌,用於 POSTPUT PATCHDELETE 請求。

當然,如前所述,某些伺服器端框架(例如 Laravel)在發送請求時會自動處理 CSRF 令牌的包含。 因此,當使用這些框架之一時,不需要額外的配置。

但是,如果您需要手動處理 CSRF 保護,一種方法是將 CSRF 令牌作為每個回應的 prop 包含在內。然後,您可以在發送 Inertia 請求時使用該令牌。

import { router, usePage } from '@inertiajs/vue3'

const page = usePage()

router.post('/users', {
  _token: page.props.csrf_token,
  name: 'John Doe',
  email: 'john.doe@example.com',
})

您甚至可以使用 Inertia 的共享資料功能,自動將 csrf_token 與每個回應一起包含。

但是,更好的方法是使用已經內建在 axios 中的 CSRF 功能來實現此目的。Axios 是 Inertia 在底層使用的 HTTP 函式庫。

Axios 會自動檢查是否存在 XSRF-TOKEN cookie。如果存在,它會將令牌包含在任何發送的請求的 X-XSRF-TOKEN header 中。

實現此目的最簡單的方法是使用伺服器端中間件。只需在每個回應中包含 XSRF-TOKENcookie,然後使用 axios 發送的請求中的 X-XSRF-TOKEN header 來驗證令牌。

處理不匹配

當發生 CSRF 令牌不匹配時,您的伺服器端框架可能會拋出一個導致錯誤回應的例外。例如,當使用 Laravel 時,會拋出一個 TokenMismatchException,這會導致一個 419 錯誤頁面。由於這不是一個有效的 Inertia 回應,因此錯誤會顯示在一個模式視窗中。

顯然,這不是一個很好的使用者體驗。處理這些錯誤的更好方法是重新導向回上一頁,並顯示一個頁面已過期的快閃訊息。這會產生一個有效的 Inertia 回應,其中快閃訊息可用作一個 prop,然後您可以將其顯示給使用者。當然,您需要與 Inertia 分享您的快閃訊息才能使此功能正常運作。

當使用 Laravel 時,您可以修改應用程式的例外處理器,以便在向 session 發送訊息時自動將使用者重新導向回他們先前所在的頁面。為了實現這一點,您可以使用應用程式的 bootstrap/app.php 檔案中的respond 例外方法。

use Symfony\Component\HttpFoundation\Response;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->respond(function (Response $response) {
        if ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'The page expired, please try again.',
            ]);
        }

        return $response;
    });
});

最終結果是為您的使用者帶來更好的體驗。使用者不會看到錯誤模式視窗,而是看到一則頁面「已過期」的訊息,並被要求再次嘗試。