> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Fetch Metadata

> 透過使用 Sec-Fetch-* 標頭的安全性 middleware,保護 Laravel 應用免受 CSRF 攻擊與跨站請求。

## 概觀

[revolution/laravel-fetch-metadata](https://github.com/invokable/laravel-fetch-metadata) 是一個驗證瀏覽器所傳送的 `Sec-Fetch-*` HTTP 標頭的安全性 middleware 套件。可依請求的來源、模式、目的地、是否有使用者操作等條件,控制允許的請求。

透過活用瀏覽器內建的安全性功能,可以在不影響正常使用者體驗的前提下,防止來自非法 origin 的惡意請求。

<Info>
  在 Laravel 13 中,CSRF 保護的 Origin 驗證會使用 `Sec-Fetch-Site` 標頭。詳細請參閱[CSRF 保護](/zh-TW/csrf)。
</Info>

Fetch Metadata 的詳細規範請參閱 [MDN 文件](https://developer.mozilla.org/ja/docs/Glossary/Fetch_metadata_request_header)。

## 安裝

```bash theme={null}
composer require revolution/laravel-fetch-metadata
```

### 註冊 middleware 別名

在 `bootstrap/app.php` 註冊 middleware 別名。

```php theme={null}
use Illuminate\Foundation\Configuration\Middleware;
use Revolution\FetchMetadata\Middleware\SecFetchSite;
use Revolution\FetchMetadata\Middleware\SecFetchMode;
use Revolution\FetchMetadata\Middleware\SecFetchDest;
use Revolution\FetchMetadata\Middleware\SecFetchUser;

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'sec-fetch-site' => SecFetchSite::class,
        'sec-fetch-mode' => SecFetchMode::class,
        'sec-fetch-dest' => SecFetchDest::class,
        'sec-fetch-user' => SecFetchUser::class,
    ]);
})
```

也可以只使用部分 middleware。別名名稱可自由變更。

## Middleware 說明

### SecFetchSite

`Sec-Fetch-Site` 標頭表示請求發生來源與目標 origin 的關係。預設僅允許 `same-origin` 與 `none`(直接存取)。

| 值             | 說明                      |
| ------------- | ----------------------- |
| `same-origin` | 來自相同 origin 的請求         |
| `same-site`   | 來自子網域等相同 site 的請求       |
| `cross-site`  | 來自不同 site 的請求           |
| `none`        | 使用者直接輸入 URL 等,以導航為起點的請求 |

詳細請參閱 [MDN 文件](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Sec-Fetch-Site)。

### SecFetchMode

`Sec-Fetch-Mode` 標頭表示請求的模式。預設允許 `navigate` 與 `cors`。

| 值             | 說明             |
| ------------- | -------------- |
| `navigate`    | 連結點擊或表單提交等導航請求 |
| `cors`        | CORS 請求        |
| `no-cors`     | no-cors 請求     |
| `same-origin` | 同 origin 請求    |
| `websocket`   | WebSocket 連線請求 |

詳細請參閱 [MDN 文件](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Sec-Fetch-Mode)。

### SecFetchDest

`Sec-Fetch-Dest` 標頭表示請求的目的地資源類型。

詳細請參閱 [MDN 文件](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Sec-Fetch-Dest)。

### SecFetchUser

`Sec-Fetch-User` 標頭表示請求是否由使用者操作而觸發。值僅有 `?1`(有使用者操作)。

<Warning>
  使用 `SecFetchUser` middleware 時,搜尋引擎爬蟲與 AI Agent 也會被阻擋。不應用於需要被索引的公開頁面。
</Warning>

## 路由使用範例

### 基本使用

```php theme={null}
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;

Route::post('user/update-password', function (Request $request) {
    //
})->middleware('sec-fetch-site');
```

### 以參數指定允許的值

```php theme={null}
Route::post('user/update-password', function (Request $request) {
    //
})->middleware('sec-fetch-site:cross-site');
```

### 指定多個參數

```php theme={null}
Route::post('user/update-password', function (Request $request) {
    //
})->middleware('sec-fetch-site:same-origin,cross-site');
```

### 不使用別名

```php theme={null}
use Revolution\FetchMetadata\Middleware\SecFetchSite;

Route::post('user/update-password', function (Request $request) {
    //
})->middleware(SecFetchSite::class.':same-origin,cross-site');
```

### 組合多個 middleware

```php theme={null}
Route::post('user/update-profile', function (Request $request) {
    //
})->middleware(['sec-fetch-site:same-origin', 'sec-fetch-mode:navigate']);
```

## 錯誤處理

當 `Sec-Fetch-*` 標頭的值不合法時,會拋出 `Symfony\Component\HttpKernel\Exception\BadRequestHttpException`。

可在 `bootstrap/app.php` 中自訂回應。

```php theme={null}
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (BadRequestHttpException $e, Request $request) {
        if ($request->expectsJson()) {
            return response()->json([
                'message' => $e->getMessage(),
            ], 400);
        }
    });
})
```

## 與 CSRF 保護的關係

在 Laravel 13 中,`PreventRequestForgery` middleware 作為 CSRF 保護的第一步,會使用 `Sec-Fetch-Site` 標頭進行 Origin 驗證。本套件可進一步以更細的粒度活用 Fetch Metadata 標頭,強化應用程式的安全性。

詳細請參閱[CSRF 保護](/zh-TW/csrf)。

<Info>
  最新資訊請參閱 [GitHub 儲存庫](https://github.com/invokable/laravel-fetch-metadata)。
</Info>


## Related topics

- [從 Laravel 12 升級到 13 指南](/zh-TW/blog/upgrade-12-to-13.md)
- [Socialite - Laravel Bluesky](/zh-TW/packages/laravel-bluesky/socialite.md)
- [Laravel MCP](/zh-TW/mcp.md)
- [Session Context 與篩選](/zh-TW/packages/laravel-copilot-sdk/session-context.md)
- [Session 生命週期事件](/zh-TW/packages/laravel-copilot-sdk/session-lifecycle-event.md)
