概要
middleware.ts をプロジェクトルートに置くと、ページレンダリング前にリクエストを横断的に処理できる。
Cookie の存在チェックで未認証ユーザーをログインページへリダイレクトし、保護ルートへのアクセスを制御する。
インストール
# 追加インストールは不要
middleware.ts の実装
// middleware.ts(プロジェクトルートに配置)
import { NextRequest, NextResponse } from "next/server";
const PROTECTED_PATHS = ["/dashboard", "/settings", "/profile"];
const LOGIN_PATH = "/login";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 保護対象パスかどうか確認
const isProtected = PROTECTED_PATHS.some((path) => pathname.startsWith(path));
if (!isProtected) return NextResponse.next();
// Cookie でセッションの有無を確認
const sessionToken = request.cookies.get("session-token");
if (sessionToken) return NextResponse.next();
// 未認証 → ログインページへリダイレクト(元 URL をクエリに付与)
const loginUrl = new URL(LOGIN_PATH, request.url);
loginUrl.searchParams.set("redirect", pathname);
return NextResponse.redirect(loginUrl);
}
export const config = {
matcher: [
/*
* 以下を除くすべてのパスにマッチする:
* - _next/static(静的ファイル)
* - _next/image(画像最適化)
* - favicon.ico
* - API ルート(/api/)
*/
"/((?!_next/static|_next/image|favicon.ico|api/).*)",
],
};
ログイン後のリダイレクト先処理(オプション)
// app/login/page.tsx
import { redirect } from "next/navigation";
type Props = {
searchParams: Promise<{ redirect?: string }>;
};
export default async function LoginPage({ searchParams }: Props) {
const { redirect: redirectTo } = await searchParams;
async function handleLogin(formData: FormData) {
"use server";
// ... 認証処理 ...
// 成功時は元のページへ戻す
redirect(redirectTo ?? "/dashboard");
}
return (
<form action={handleLogin} className="space-y-4 max-w-sm mx-auto mt-16">
<input name="email" type="email" placeholder="メールアドレス" className="w-full rounded border px-3 py-2 text-sm" />
<input name="password" type="password" placeholder="パスワード" className="w-full rounded border px-3 py-2 text-sm" />
<button type="submit" className="w-full rounded bg-blue-600 px-4 py-2 text-sm text-white">
ログイン
</button>
</form>
);
}
ポイント
middleware.tsはプロジェクトルート(src/を使っている場合はsrc/middleware.ts)に配置するconfig.matcherで Middleware を適用するパスを絞ると不要なリクエストへの処理を避けられるrequest.cookies.get()で Cookie を読み取れる。Edge Runtime で動作するためnode:cryptoなどの Node.js 専用 API は使えない- 実際の JWT 署名検証が必要な場合は Edge 対応ライブラリ(
joseなど)を使う。本サンプルは Cookie 存在チェックによるルート保護の構造を示す - リダイレクト先の
redirectクエリを保持することで、ログイン後に元ページへ戻る UX が実現できる