メインコンテンツにスキップ
ZetLinker Logo
Next.js

中小企業のNext.jsフルスクラッチで、Server Actions のセキュリティを現実的に守る|Data Access Layer の置き方

Conclusion

Server Actions と Data Access Layer の役割分担を最初に決めておくことが、中小企業向けフルスクラッチで現実的にセキュリティを守る出発点になります。

Next.js 16 系の App Router で Server Actions を使う以上、middleware だけの認証では足りません。Data Access Layer (DAL) に認可ロジックを集約し、Zod 検証と DTO 返却を最低ラインに置く。中小企業向けフルスクラッチで「やりすぎず、抜けも作らない」セキュリティ設計を、受託の現場感で整理します。

9分で読めます
Next.jsNext.jsセキュリティServer Actions中小企業AI駆動開発

中小企業向けに Next.js のフルスクラッチ受託をやっていると、最近は App Router 前提の新規案件がほぼすべてになりました。Server Components と Server Actions を中心に組む構成です。

このとき、地味に悩ましいのが「Server Actions のセキュリティをどこまで真面目にやるか」という線引きです。Next.js 公式のデータセキュリティガイドでも、Server Actions は「常に hostile(敵対的)に扱え」と明記されていて、ページ単位の認証チェックが Server Actions に伝播しない、という前提が強調されています。

大手向けの SaaS だと専属のセキュリティ担当がいて要件を引いてくれますが、中小企業向けのフルスクラッチでは情シスが兼任で1人体制、ということも珍しくありません。IT 人材は 2026年から 2030年にかけて最大 80万人弱不足するという経済産業省の試算もあり、社内にセキュリティのノウハウが薄いまま業務システムが先行して動いている状態は、今後さらに増えそうです。

本記事では、中小企業向けの Next.js フルスクラッチで現実的に運用できる「Server Actions と Data Access Layer の置き方」を、私たちの受託現場の感覚で整理します。

なぜ middleware だけの認証では足りないのか

まず、設計の前提としてはっきりさせておきたいのが、「middleware だけに認証を寄せると危ない」という話です。

2025年に CVE-2025-29927 という重大な脆弱性が公開され、Next.js の middleware ベース認証の限界が広く知られるようになりました。WorkOS の2026年版の認証ガイドでも、middleware を「玄関の警備員」、Data Access Layer を「搭乗ゲートでの本人確認」に例え、両方そろってはじめて防御が成立する、という整理がされています。

中小企業向けの受託でも、これは現実的に効いてきます。たとえばこんなケースです。

  • 経営者向けの売上管理画面と、現場スタッフの入力画面が同じ Next.js アプリに同居している
  • 役割(role)によって、見せるデータと、書き換えていいデータが違う
  • 退職者が出たときに、すぐに権限を絞りたい

middleware だけの認証だと、Server Actions 内のクエリが「ログイン済みなら誰でも実行できる」状態になりがちです。退職者のセッションが残っていた、ロールチェックが特定の画面にしかなかった、といった事故が起こりやすくなります。

このあたりの考え方は、私たちの 【2026年版】Next.js 16 + Firebase Authentication で実現するセキュアな会員制サイト構築 でも触れていますが、本記事ではより業務システム寄りの観点で深掘りします。

Data Access Layer (DAL) を中小企業向けにどう置くか

Next.js 公式ガイドでは、データ取得と認可ロジックを集約する「Data Access Layer(DAL)」のパターンが推奨されています。私たちの受託案件でも、画面数が 20 を超えるあたりから、DAL を切らないと保守がしんどくなる感覚があります。

中小企業向けのフルスクラッチでは、シンプルに次のような置き方にすることが多いです。

  • src/server/dal/ 配下に、ドメイン単位でファイルを分ける(例: orders.ts, customers.ts, users.ts
  • 各ファイルの先頭で import "server-only" を必ず付け、クライアントバンドルに混入しない構成にする
  • どの関数も「セッション検証 → 認可チェック → クエリ → DTO 変換」の順で書く
  • 戻り値は ORM のインスタンスではなく、画面に必要な分だけのプレーンオブジェクト(DTO)を返す

ざっくり書くと、こんなイメージです。

// src/server/dal/orders.ts
import "server-only";
import { verifySession } from "@/server/auth/session";
import { prisma } from "@/server/prisma";

export async function listOrdersForCurrentUser() {
  const session = await verifySession();
  if (session.role !== "staff" && session.role !== "manager") {
    throw new Error("FORBIDDEN");
  }

  const orders = await prisma.order.findMany({
    where: { tenantId: session.tenantId },
    select: { id: true, code: true, totalAmount: true, status: true },
  });

  return orders;
}

ポイントは、「呼び出し側でロールチェックを書かない」という運用にすることです。中小企業向けの受託では、エンジニアが入れ替わっても DAL を見ればドメインごとの認可ルールが分かる、という状態を維持するのが現実的です。

このパターンは Next.js 公式のデータセキュリティガイドでも推奨されていて、特別に複雑なフレームワークを足す必要はありません。

ここで一度お知らせ

15分のカジュアル相談

事例・要件未定でもOK/営業はしません/所要時間15分

カジュアルに相談する

Server Actions 側でやるべき最低ライン

DAL を切ったうえで、Server Actions 側では次のラインを守るようにしています。

  1. Zod などで入力スキーマを必ず検証する
  2. DAL の関数を呼ぶ前に、もう一度セッションを検証する
  3. エラーメッセージに内部情報を載せない
  4. 戻り値も DTO に揃える(ORM 直返しをしない)

Server Actionsを守る多層防御のアーキテクチャ図。リクエストがmiddleware(玄関の警備員)、Data Access Layer(搭乗ゲートの本人確認、セッション検証・認可チェック・DTO変換)、Server Actions(Zod検証とエラー分離)の3層を順に通過する構造を示す。

Authgear の2026年版 Next.js セキュリティガイドでも、Server Actions の入力は常に Zod 等で検証することが「最低ライン」として強調されています。CSRF トークンを Next.js 側で自動的に発行する仕組みは存在しないので、入力検証と認可の二段構えで守る、というのが 2026 年時点の現実解です。

たとえば、受注ステータスを更新する Server Action なら、こんな書き方になります。

// src/app/(dashboard)/orders/actions.ts
"use server";

import { z } from "zod";
import { verifySession } from "@/server/auth/session";
import { updateOrderStatus } from "@/server/dal/orders";

const schema = z.object({
  orderId: z.string().min(1),
  status: z.enum(["preparing", "shipped", "completed"]),
});

export async function updateOrderStatusAction(formData: FormData) {
  const session = await verifySession();
  const parsed = schema.safeParse({
    orderId: formData.get("orderId"),
    status: formData.get("status"),
  });
  if (!parsed.success) {
    return { ok: false, message: "入力値が不正です" };
  }

  try {
    await updateOrderStatus({
      session,
      orderId: parsed.data.orderId,
      status: parsed.data.status,
    });
    return { ok: true };
  } catch {
    return { ok: false, message: "更新に失敗しました" };
  }
}

ありがちなミスとして、catch で受け取った error のメッセージをそのままユーザーに返してしまう、というものがあります。これを続けていると、スタックトレースや内部 ID が UI 経由で漏れることがあります。中小企業向けの業務システムでも、データの取り扱い責任は同じなので、エラーは「ユーザー向け文言」と「ログ向け詳細」を分けて扱うことを徹底しています。

中小企業向けに「やりすぎないライン」をどう引くか

セキュリティの話は、踏み込もうと思えばどこまでも踏み込めます。ただ、中小企業向けの受託で大手 SaaS と同じレベルの設計を要求すると、予算と納期が一気に現実から離れます。

私たちが受託の見積り段階で意識しているのは、「最低限ここまではやる」「やるかどうかは要件次第」のラインを最初に切ることです。

最低限ここまではやる:

  • middleware で未ログインを弾く
  • DAL でセッション検証と role チェックを集中管理する
  • Server Actions で Zod 検証と認可チェック
  • ログには個人情報を載せず、外形のみ残す(エラートラッキングと組み合わせる)

要件次第で足すもの:

  • 監査ログ(誰が何をいつ更新したか)の専用テーブル
  • 多要素認証(MFA)
  • IP 制限・地理制限
  • 退職者処理の SOP と仕組み化

中小企業向けの場合、監査ログや MFA は「いま必要ですか?」を率直に確認します。実態としては、まずは最低ラインを満たしたうえで、運用しながら順次足していくケースが多いです。AI 駆動開発で実装速度は上がっていますが、「全部やる」ではなく「必要なところから順に」という考え方は変えていません。

このあたりは 【2026年版】中小企業の社内業務を Next.js で作り直す実務ガイド【2026年版】Next.js × AIエージェントで業務を自動化する実務ガイド でも触れているので、業務システム側の文脈と合わせて読むとイメージがつきやすいかもしれません。

AI 駆動開発との合わせ技で、セキュリティ実装の取りこぼしを減らす

最後に、AI 駆動開発との掛け算の話を少しだけ。

Cursor や Claude Code を使うと、Server Actions と DAL のひな型を一気に生成できます。便利な反面、「生成されたままで認可チェックが抜けている」「Zod スキーマが付いていない」といった抜け漏れが起きやすいのも事実です。

私たちの社内では、AI に対して次のような前提を毎回渡すようにしています。

  • 「Server Actions は必ず Zod でスキーマを定義してください」
  • 「DAL 関数の冒頭で verifySession() と role チェックを入れてください」
  • 「戻り値は DTO で、ORM のインスタンスを直接返さないでください」
  • error.message をそのままユーザーに返さないでください」

このルールを Claude Code の CLAUDE.md や Cursor の Rules に書いておくと、生成コードの初期品質が一段上がります。AI 駆動開発の使い分けは Cursor と Claude Code をどう使い分けているか|中小企業向け Next.js 受託の現場 にもまとめてあります。

「AI で速く作る」と「セキュリティを現実的に守る」は対立しません。ルールを言語化して AI に渡し、人間が DAL のレビューに集中する。この役割分担が、中小企業向けフルスクラッチでも現実的に回るやり方だと感じています。

まとめ

  • Server Actions は「常に敵対的」に扱うのが 2026年時点の前提
  • middleware だけの認証では足りない。Data Access Layer に認可ロジックを集約する
  • 中小企業向けでは「最低限のライン」と「要件次第で足すもの」を最初に切り分ける
  • Zod による入力検証、DTO 返却、エラーの分離は最低限でやる
  • AI 駆動開発との合わせ技で、抜け漏れを減らしつつ実装速度を保つ

Next.js フルスクラッチでの業務システム開発を検討中の中小企業の方は、株式会社ゼットリンカーの無料相談フォーム からご相談ください。ご予算と要件をうかがったうえで、現実的な設計と見積りをご提案します。

本記事は Next.js 16.x 時点の情報です

最終更新:2026年5月26日

Share this article

15分のカジュアル相談

事例・要件未定でもOK/営業はしません/所要時間15分

カジュアルに相談する

次に読む記事

ALL ARTICLES →
01 / 03Next.js

中小企業のNext.jsフルスクラッチで、セキュリティをどう担保するか|2026年版チェックリスト(認証・入力検証・脆弱性対策)

「Next.js はセキュリティ的に大丈夫?」に総論で答えます。2026年5月の大型セキュリティリリース(middleware認可迂回 CVE-2026-44575、16.2.6で修正)を起点に、本体のパッチ追従、認証・認可をData Access Layerに寄せる設計、Zodによる入力検証とServer Actions、環境変数・シークレット管理、依存パッケージの脆弱性、デプロイ設定までを、中小企業向けフルスクラッチの現実的なラインで整理。各論は詳細記事へリンクします。

·9
02 / 03Next.js

中小企業のNext.jsフルスクラッチで、テストをどこまで書くか|AI駆動開発時代の現実的なテスト戦略 (Vitest + Playwright)

中小企業向けの Next.js フルスクラッチ受託で、テストをどこまで書くか。Next.js 16 公式が標準とする Vitest + Playwright 構成と、async Server Component が Vitest 非対応であるという制約を踏まえ、限られた予算で「何をテストしないか」を先に決める考え方を整理します。AI 駆動開発でテストを速く書けるいまだからこそ、テストケースの妥当性は人間が責任を持つ、という現場のラインを共有します。

·8
03 / 03AI開発

社内マニュアルをAIで検索可能にする|Next.js × ベクトル検索の始め方

「あのマニュアルどこだっけ?」を解決するベクトル検索の仕組みを、非エンジニアにも分かるように解説。Next.js 16 × OpenAI Embeddings × ベクトルDBで社内FAQ検索を最小構成で始める方法をお伝えします。

·9