Laravel/PHPと比較して理解するAstroのセッション管理、ミドルウェア、CSRF対策
この記事は「BEMA Lab Advent Calendar 2025」の11日目の記事です。
※本アドベントカレンダーの11日目の投稿となります。
はじめに
AstroはSSGだけでなくSSRも可能なWebフレームワークです。 フロントエンドの主流であるNext.jsも強力ですが、コンポーネントの境界線("use client")や複雑なキャッシュ管理など、独自の学習コストが高い側面もあります。対してAstroは素直なMPA構造を採用しており、現代的な機能を持ちつつも「素のPHP」に近い感覚で扱えるのが魅力です。
本稿では、Laravel等の開発経験があるPHPエンジニアに向けて、Astroのセッション管理やミドルウェアの挙動、そしてCSRF対策を既存の知識と比較しながら解説します。
セッションの仕組み(おさらい)
セッションはサーバーとブラウザ間で一時的にデータを保持しておくための仕組みです。データの中身はサーバー側に保存し、ブラウザ側にはそのデータにアクセスするための識別情報となるセッションIDだけを持たせます。
言語やフレームワークを問わず、セッションの基本構造は以下の3要素で成り立っています。
- サーバーはブラウザに対してセッションIDを発行します。
- ブラウザはこのセッションIDをCookieとして保存し、以降のリクエストごとにサーバーへ送信します。
- サーバーでは、受け取ったセッションIDに対応するデータをファイルやDBなどのストレージから引き出すことで、誰からのアクセスか、どのような状態かを復元します。
このストレージへの保存や取得をどう実装するかが、フレームワークごとの設計思想の違いとして現れます。
PHP / Laravel のセッション管理
PHPは言語レベルでセッション機構 $_SESSION を持っています。
デフォルトではファイルシステムベースであり、設定された一時ディレクトリにセッションデータをシリアライズしてファイルとして保存します。これはシンプルですが、サーバーが複数台構成になった際にセッション共有が難しくなるという課題がありました。
この課題を、Laravelではドライバーベースのアーキテクチャを採用することで解決しています。これにより .env や config/session.php を書き換えるだけで、データの保存先を切り替えることができます。開発環境ではfileドライバーを使い、本番環境ではredisやdatabaseドライバーを使う、といったことも可能です。
Astro のセッション管理
Astroのセッション管理も、現代的なWebフレームワークとして、Laravelと同様にドライバーベースのアーキテクチャを採用しており、内部で Unstorage というストレージ抽象化レイヤーを利用しています。 これにより、セッションデータの保存先を柔軟に切り替えることが可能です。
Laravelと少し異なる点としては、Astroでは、利用するアダプター(Node.js, Netlify, Cloudflareなど)によってセッションのドライバーが自動的に構成されます。
例えば、 @astrojs/node アダプターを使用する場合はローカルのファイルシステムやメモリが使用されますが、 @astrojs/cloudflare アダプターを使用する場合は、エッジ環境に適したCloudflare KVなどがバックエンドとして機能します。 設定ファイル astro.config.mjs で明示的にドライバーを指定し、Redisなどを利用することも可能です。
補足: Better-Authのような認証ライブラリは独自のセッション管理機構を持っているため、標準のAstro.sessionと併用したり、認証周りについてはライブラリ側に任せたりといった柔軟な使い分けがなされます。
AstroとLaravelのセッションAPIの比較
実際のコードで比較すると、その類似性と、JavaScript特有の非同期処理による違いが見えてきます。
値の保存
Laravelでは同期的に処理が行われます。
// ヘルパー関数を使用する場合
session(['user_id' => 123]);
// Requestインスタンスを使用する場合
$request->session()->put('user_id', 123);Astroでは基本的には非同期(await)で扱います。
await Astro.session?.set('user_id', 123);値の取得
Laravel
$userId = session('user_id', 'default_value');Astro
const userId = await Astro.session?.get('user_id') ?? 'default_value';AstroのAPIは非常にシンプルですが、すべての操作がPromiseを返す非同期である点がポイントです。これは、バックエンドがRedisやデータベースに変わった際にも、イベントループをブロックしないための設計であると思われます。
ミドルウェアとlocalsによる情報の引き継ぎ
Laravelのミドルウェアで$requestに値をセットし、後続の処理へ情報を引き継ぐ流れは、Astroのミドルウェアのcontext.localsで実現できます。
Next.jsのミドルウェアはEdge Runtimeの制約があり、標準的なAPIが使えないなど独自の制限を意識する必要があります。対してAstroは、サーバー側でリクエストを処理してレスポンスを返すという、Laravelに近いメンタルモデルで動作します。
// src/middleware.ts
export const onRequest = defineMiddleware(async (context, next) => {
// セッションからユーザーを取得し、localsに格納する
context.locals.user = await context.session.get('user');
return next();
});context.localsは、ミドルウェアからAPIルートや.astroファイルへリクエスト固有の情報を渡すためのオブジェクトです。ここに入れたデータは、1回のリクエストの生存期間中のみ保持されます。
---
// ページコンポーネントでlocalsからデータを取り出す
const { user } = Astro.locals;
---
<h1>ようこそ、{user.name}さん</h1>フロントエンドの状態管理ライブラリを使わず、リクエストのライフサイクル内で完結して情報を扱う設計は、Laravelエンジニアにとって馴染みやすいものです。
CSRF対策の違い
セッションを利用する上で避けて通れないのがCSRF(クロスサイトリクエストフォージェリ)対策ですが、ここにはアプローチの違いがあります。
Laravel: トークン方式
従来のPHPフレームワークでは、フォーム内にトークンを埋め込む方式が主流でした。
<form method="POST">
@csrf <input type="text" name="email">
</form>これは、古いブラウザ仕様(他サイトからのPOSTでもCookieを送信してしまう)に対する防御策です。
Astro: SameSite属性付きCookie+Originヘッダー検証
Astroなどの現代的なフレームワークは、ブラウザのセキュリティ機能の進化に合わせたアプローチを取っています。
- SameSite属性付きCookie: AstroではセッションIDなどのCookieにはデフォルトで
SameSite属性が付与され、クロスサイトなリクエストでは送信されないよう制御されます。 - Originヘッダー検証: Astroはデフォルト設定
で、リクエスト送信元のドメイン(Origin)とサーバーのドメインが一致するかを自動的にチェックします。一致しない場合、リクエストは拒否されます。
これにより、開発者が毎回トークンを埋め込まなくても、ブラウザ標準の機能で一定のセキュリティレベルが担保されます。
SameSite属性を指定したCookieとOriginヘッダー検証によるCSRF対策については、PHPerKaigi 2024でのhiro_y氏の発表でとてもわかりやすくまとめられています。
まとめ
Astroのセッション管理やミドルウェアの設計は、Laravel開発者にとって非常に馴染みやすい設計になっていますが、CSRF対策は異なるアプローチが取られていることがお分かりいただけたかと思います。
Astroは単なる静的サイトビルダーではなく、フルスタックなWebアプリケーションフレームワークとして十分な機能を有しています。 まだAstroを触ったことがないPHPエンジニアの方は、ぜひこの「懐かしくも新しい」フレームワークにチャレンジしてみてください。
この記事を書いた人

What is BEMA!?
Be Engineer, More Agile





