🚓
Next.js & Vercelで特定の国からのアクセスをブロック/許可
はじめに
- 特定の国からのアクセスを middlware でブロック/許可する簡易方法をまとめます。
- 作業したコードは以下になります。
結論
middleware.ts
で、request.geo.country
を参照することで、アクセス元の国を取得でき、値に応じて処理を記載すればよいです。以下は日本のみアクセスを許可している場合の例です。
middleware.ts
// middleware.ts
import { NextResponse, type NextRequest } from "next/server";
export function middleware(request: NextRequest) {
const country = request.geo?.country;
if (process.env.NODE_ENV === "production") {
if (country && country !== "JP") {
console.info(
`IPアドレスが日本以外のため、アクセスを拒否しました。[request.ip = ${request.ip}]`
);
return new NextResponse(null, { status: 401 });
}
}
}
実装
実際に、Next.js, Vercel で実装してみます。
Next.jsプロジェクトの新規作成
作業するプロジェクトを新規に作成していきます。
長いので、折りたたんでおきます。
新規プロジェクト作成と初期環境構築の手順詳細
$ pnpm create next-app@latest nextjs-country-block-sample --typescript --eslint --import-alias "@/*" --src-dir --use-pnpm --tailwind --app
$ cd nextjs-country-block-sample
以下の通り不要な設定を削除し、プロジェクトの初期環境を構築します。
$ mkdir src/styles
$ mv src/app/globals.css src/styles/globals.css
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
src/app/page.tsx
export default function Home() {
return (
<main className="text-lg">
テストページ
</main>
)
}
src/app/layout.tsx
import '@/styles/globals.css'
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body className="">{children}</body>
</html>
);
}
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
plugins: [],
};
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
+ "baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
コミットします。
$ pnpm build
$ git add .
$ git commit -m "新規にプロジェクトを作成し, 作業環境を構築"
特定の国をブロック/許可する
日本以外からのアクセスをブロックする場合は、request.geo.country
が JP
になるため、JP
でない場合に処理を行うようにします。
$ touch src/middleware.ts
middleware.ts
// middleware.ts
import { NextResponse, type NextRequest } from "next/server";
export function middleware(request: NextRequest) {
const country = request.geo?.country;
// 接続元の国を表示
console.info(country);
if (process.env.NODE_ENV === "production") {
if (country && country !== "JP") {
console.info(
`IPアドレスが日本以外のため、アクセスを拒否しました。[request.ip = ${request.ip}]`
);
return new NextResponse(null, { status: 401 });
}
}
}
コミットします。
$ pnpm build
$ git add .
$ git commit -m "日本以外のアクセスを拒否する"
動作確認
動作確認するためには、Vercel などにデプロイする必要があります。ローカル環境では、pnpm dev
あるいは pnpm start
のいずれでも、request.geo.country
が undefined
になってしまうためです。
- GitHub にリポジトリを作成します。
- Vercel にデプロイします。
ブラウザで開きます。
Vercel のログを確認します。
見にくいのでログの部分だけ拡大します。
- 日本からのアクセスは JP と表示されています。
- アメリカからのアクセスは US と表示されています。
- アメリカからのアクセスはアクセスが拒否されています。
まとめ
- 特定の国からのアクセスをブロック/許可する方法を紹介しました。
- 作業したコードは以下にあります。
Discussion