0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vercel の静的ホスティングでBASIC認証&IPアドレス制限

0
Last updated at Posted at 2026-01-15

これは何?

自分用メモです。

Vercel で静的サイト(※Honkit ビルドなど)をホスティングする際に BASIC認証 および IPアドレス制限 を行う middleware.ts のスニペット。

Honkit でビルドされた静的ファイル(html, css, ...)が _book/ ディレクトリに出力、静的サイトホスティングされる例。

image.png

導入

事前に @vercel/functions を package.json の dependencies への追加します。

npm install @vercel/functions

その後、下記の middleware.ts をプロジェクトルートに配置します。

middleware.ts
import { next } from "@vercel/functions";

export const config = {
  matcher: "/(.*)",
};

export default function middleware(request: Request) {
  // 許可IPアドレスチェック.
  if (isAllowedIpAddress(request)) {
    return next();
  }

  // BASIC認証.
  if (isAuthorized(request)) {
    return next();
  }

  return new Response("Basic Auth required", {
    status: 401,
    headers: {
      "WWW-Authenticate": 'Basic realm="Secure Area"',
    },
  });
}

/**
 * 許可IPアドレスチェック.
 *
 * @param {*} request
 * @returns {boolean} true = 許可IPアドレス, false = 許可IPアドレスではない
 */
function isAllowedIpAddress(request: Request) {
  // source IP address.
  const ips = request.headers.get("x-forwarded-for") ?? "";
  const ip = ips.split(",").pop(); // 偽装防止の為、末尾を.

  // access denied when "x-forwarded-for" is invalid.
  if (!ip) {
    return false;
  }

  // access denied when "ALLOWED_IP_ADDRESSES" is empty.
  if (!process.env.ALLOWED_IP_ADDRESSES) {
    return false;
  }

  // load allowed IP addresses from environment variable.
  const allowedIps = process.env.ALLOWED_IP_ADDRESSES.split(",").map((ip) => ip.trim());

  return allowedIps.includes(ip);
}

/**
 * BASIC認証.
 *
 * @param {*} request
 * @returns {boolean} true = 認証OK, false = 認証NG
 */
function isAuthorized(request: Request) {
  const authorizationHeader = request.headers.get("authorization");
  if (!authorizationHeader) {
    return false;
  }

  const basicAuth = authorizationHeader.split(" ")[1];
  if (!basicAuth) {
    return false;
  }

  const [user, password] = atob(basicAuth).toString().split(":");
  const authorized =
    user === process.env.BASIC_AUTH_USER && password === process.env.BASIC_AUTH_PASSWORD;

  return authorized;
}

環境変数で、BASIC認証のID/Password、アクセス許可するIPアドレスを設定します。

  • ALLOWED_IP_ADDRESSES ... comma separeted ip addresses
  • BASIC_AUTH_USER ... username
  • BASIC_AUTH_PASSWORD ... password

image.png

参考(公式)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?