概要
Next.jsで作成したサイトを一部の人しか見れないようにするため、
大したものじゃなくて良いけど一応パスワードかけときたいなと思い、方法を検索。
Vercelのオプションでパスワード認証があったけど、高すぎる。
かといってNextAuth.js
は正直難しそうだったため、middleware
で簡易的な設定を決意。
しかし、検索してると出てくる情報が、
middlewareフォルダ
を作って、そこにmiddleware.ts
を置くべきあったり、
または、pages/
下層にmiddleware.ts
を置くとあるが、
src/app
ディレクトリを使っている場合はどうすればええんや等、
初学者には色々と悩むポイントがあったのでここに備忘録としてまとめておく。
結論
src下層にmiddleware.ts
を直接置けば機能する。
ディレクトリ構成(おおよそのものを表示)
プロジェクトルート
│
├── public/ # 静的ファイル
│
├── src/ # ソースコード
│ ├── app/ # アプリケーションファイル
│ └── middleware.ts # ミドルウェア(これ)
│
├── package.json # パッケージ設定
└── tsconfig.json # TypeScript設定
middleware.ts
のコードは下記にすれば良い。
サンプルコード(パスワード直書きパターン)
// Next.jsのサーバーサイドルーティング機能から必要な型をインポート
import { NextRequest, NextResponse } from 'next/server';
// ミドルウェアの設定。全てのルート('/')でこのミドルウェアを適用
export const config = {
matcher: ['/']
};
// ミドルウェア関数を定義。NextRequestオブジェクトを受け取る
export function middleware(request: NextRequest) {
// リクエストヘッダーからauthorizationを取得
const basicAuth = request.headers.get('authorization');
if (basicAuth) {
// Basic認証の値をデコードしてユーザー名とパスワードを取得
const authValue = basicAuth.split(' ')[1];
const [user, password] = atob(authValue).split(':');
// 正しいユーザー名とパスワードが提供された場合、リクエストを次の処理へ進める
if (user === 'username' && password === 'password') {
return NextResponse.next();
}
}
// 認証に失敗した場合、リダイレクト応答を返す
// ここでリダイレクト先のURLを指定します。例えば、'/'へのリダイレクト
return NextResponse.redirect('/');
}
環境変数から取得する場合は下記。
(もちろんこちらの方が良い)
.サンプルコード(env.localから取得する場合)
// Next.jsのサーバーサイドルーティング機能から必要な型をインポート
import { NextRequest, NextResponse } from 'next/server';
// ミドルウェアの設定。全てのルート('/')でこのミドルウェアを適用
export const config = {
matcher: ['/']
};
// ミドルウェア関数を定義。NextRequestオブジェクトを受け取る
export function middleware(request: NextRequest) {
// リクエストヘッダーからauthorizationを取得
const basicAuth = request.headers.get('authorization');
if (basicAuth) {
// Basic認証の値をデコードしてユーザー名とパスワードを取得
const authValue = basicAuth.split(' ')[1];
const [user, password] = atob(authValue).split(':');
// 環境変数から正しいユーザー名とパスワードを取得
const envUser = process.env.AUTH_USER;
const envPassword = process.env.AUTH_PASSWORD;
// 環境変数の値と一致する場合、リクエストを次の処理へ進める
if (user === envUser && password === envPassword) {
return NextResponse.next();
}
}
// 認証に失敗した場合、リダイレクト応答を返す
// ここでリダイレクト先のURLを指定します。例えば、'/'ページへのリダイレクト
return NextResponse.redirect('/');
}
結果
ローカル環境であってもVercel環境であっても認証を求められるようになった。