メインコンテンツにスキップ
株式会社ゼットリンカー - Next.js システム開発専門
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 を見ればドメインごとの認可ルールが分かる、という状態を維持するのが現実的です。

そのロール自体をどう切るか(役割をいくつ作るか、どこまでを1つの役割にまとめるか)は、実装よりも業務側の要件定義の問題です。役割の決め方と、Next.js 16 で改称された proxy.ts との責務分担は社内システムの権限設計をNext.js 16でどう実装するかで詳しく整理しています。

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

この判断から次に進む

課題が整理できていなくても相談できます

困っている業務と、変えたいことだけでも大丈夫です。初回相談・モック・見積もりは無料です。

カジュアルに相談する

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

よくある質問

middleware だけで認証チェックをしてはいけないのですか?

middleware は最初の関門としては有効ですが、それだけだと Server Actions 内のクエリが「ログイン済みなら誰でも実行できる」状態になりがちです。Next.js 公式ガイドでも、Server Actions やルートハンドラ側で再度認証・認可を行うことが推奨されており、Data Access Layer に認可ロジックを集約する構成が現実的だと考えています。

中小企業の予算でも Data Access Layer (DAL) は導入できますか?

DAL は特別なライブラリを必要としません。`src/server/dal/` のような単なるディレクトリ構成と、各関数の冒頭でセッション検証・認可チェックを行うルールを徹底するだけで成立します。画面数が 20 を超えるあたりから保守性に大きな差が出るため、予算規模よりも「将来の保守を見据えるかどうか」で導入を判断するのが現実的です。

監査ログや多要素認証は最初から入れるべきですか?

案件と業界によります。個人情報や金銭を扱う業務であれば早めの導入をお勧めしますが、社内向けの業務システムであれば、まず最低ラインのセキュリティを満たしたうえで運用しながら順次足していく方針も現実的です。要件ヒアリングの段階で「いま必要か」「半年後に必要か」を切り分けるようにしています。

技術仕様・対象バージョンは本文と参照先をご確認ください。

最終更新:2026年5月26日

Share this article

課題が整理できていなくても相談できます

困っている業務と、変えたいことだけでも大丈夫です。初回相談・モック・見積もりは無料です。

カジュアルに相談する

先に整理したい方はシステム引き継ぎの初動・調査シート・AI相談プロンプトをご利用ください。未確認の項目は空欄のままご相談いただけます。

次に読む記事

ALL ARTICLES →
01 / 03Next.js

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

「Next.js はセキュリティ的に大丈夫?」に総論で答えます。2026年5月・7月の大型セキュリティリリース(middleware認可迂回 CVE-2026-44575・CVE-2026-64642等)を起点に、本体のパッチ追従、認証・認可を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

プライバシーポリシー

株式会社ゼットリンカー(以下、「当社」といいます。)は、お客様の個人情報の重要性を認識し、 その保護の徹底を図るため、以下のプライバシーポリシー(以下、「本ポリシー」といいます。)を定めます。

1. 個人情報の定義

本ポリシーにおいて「個人情報」とは、生存する個人に関する情報であって、 当該情報に含まれる氏名、生年月日その他の記述等により特定の個人を識別することができるもの、 及び他の情報と容易に照合することができ、それにより特定の個人を識別することができることとなるものを指します。

2. 個人情報の収集

当社は、お客様が当社のサービスをご利用になる際、お客様の個人情報を収集することがあります。収集する個人情報は以下の通りです:

  • 氏名
  • メールアドレス
  • 電話番号
  • 会社名・組織名
  • 住所
  • その他当社が定める入力フォームにお客様が入力する情報

3. 個人情報の利用目的

当社は、お客様からご提供いただいた個人情報を、以下の目的で利用します:

  • お客様への連絡やサービスの提供
  • お客様からのお問い合わせへの対応
  • 当社サービスの改善や新サービスの開発
  • メールマガジンの配信(お客様の同意がある場合)
  • 契約や法令等に基づく権利の行使や義務の履行
  • その他、上記利用目的に付随する目的

4. 個人情報の第三者提供

当社は、以下の場合を除き、お客様の同意なく個人情報を第三者に提供することはありません:

  • 法令に基づく場合
  • 人の生命、身体または財産の保護のために必要がある場合であって、本人の同意を得ることが困難である場合
  • 公衆衛生の向上または児童の健全な育成の推進のために特に必要がある場合
  • 国の機関もしくは地方公共団体またはその委託を受けた者が法令の定める事務を遂行することに対して協力する必要がある場合

5. 個人情報の管理

当社は、お客様の個人情報を正確かつ最新の状態に保ち、個人情報への不正アクセス、 個人情報の紛失、破損、改ざん及び漏洩などを防止するため、 セキュリティシステムの維持・管理体制の整備等の必要な措置を講じ、安全対策を実施し個人情報の厳重な管理を行います。

6. 個人情報の開示・訂正・削除

お客様は、当社に対してご自身の個人情報の開示を求めることができます。 また、開示の結果、個人情報の内容が事実でないことが判明した場合には、 速やかに訂正または削除に応じます。

7. 導入事例の公開について

当社は、お客様から依頼いただいたプロジェクトを導入事例として記事にさせていただく場合があります。導入事例として公開する場合は、以下の点に配慮いたします:

  • 機密情報や個人情報は公開いたしません
  • 社名を公開する場合は、公開内容について事前にお客様に確認いただきます
  • 社名を非公開とする場合でも、お客様のご要望に応じて公開内容を確認いただくことが可能です

8. Cookie(クッキー)の使用について

当社のウェブサイトでは、お客様により良いサービスを提供するため、Cookie を使用することがあります。 Cookie により個人を識別できる情報を収集することはありません。 お客様はブラウザの設定により Cookie の受信を拒否することができます。

9. SSL(Secure Socket Layer)について

当社のウェブサイトはSSLに対応しており、ウェブブラウザとウェブサーバーとの通信を暗号化しています。 お客様が入力する個人情報は自動的に暗号化されて送受信されるため、 万が一、第三者が傍受した場合でも内容を解読することは困難です。

10. プライバシーポリシーの変更

当社は、必要に応じて、本ポリシーの内容を変更することがあります。 変更後のプライバシーポリシーについては、当社ウェブサイトに掲載したときから効力を生じるものとします。

11. お問い合わせ

本ポリシーに関するお問い合わせは、以下の窓口までお願いいたします。

株式会社ゼットリンカー

〒160-0023

東京都新宿区西新宿3丁目3番13号西新宿水間ビル2F

代表取締役: 金原隆利

お問い合わせ先: info@zetlinker.com

制定日:2024年1月1日

最終改訂日:2026/9/10

利用規約

この利用規約(以下、「本規約」といいます。)は、株式会社ゼットリンカー(以下、「当社」といいます。)が 提供するウェブサイトおよびサービス(以下、「本サービス」といいます。)の利用条件を定めるものです。 お客様は、本規約に同意した上で、本サービスをご利用ください。

第1条(適用)

1. 本規約は、お客様と当社との間の本サービスの利用に関わる一切の関係に適用されるものとします。

2. 当社は本サービスに関し、本規約のほか、ご利用にあたってのルール等、各種の定め(以下、「個別規定」といいます。)を することがあります。これら個別規定はその名称のいかんに関わらず、本規約の一部を構成するものとします。

3. 本規約の規定と個別規定の規定が異なる場合は、個別規定において特段の定めなき限り、個別規定の規定が優先されるものとします。

第2条(定義)

本規約において使用する以下の用語は、各々以下に定める意味を有するものとします。

  • 「利用契約」とは、本規約を契約条件として当社とお客様との間で締結される、本サービスの利用契約
  • 「知的財産権」とは、著作権、特許権、実用新案権、意匠権、商標権その他の知的財産権(それらの権利を取得し、またはそれらの権利につき登録等を出願する権利を含みます。)
  • 「投稿データ」とは、お客様が本サービスを利用して投稿その他送信するコンテンツ(文章、画像、動画その他のデータを含みますがこれらに限りません。)

第3条(本サービスの提供)

1. お客様は、本規約に同意の上、当社の定める方法によって利用登録を申請し、当社がこれを承認することによって、本サービスを利用することができるようになります。

2. 当社は、お客様に以下のいずれかの事由があると判断した場合、利用登録の申請を承認しないことがあり、その理由については一切の開示義務を負わないものとします。

  • 利用登録の申請に際して虚偽の事項を届け出た場合
  • 本規約に違反したことがある者からの申請である場合
  • その他、当社が利用登録を相当でないと判断した場合

第4条(ユーザーIDおよびパスワードの管理)

1. お客様は、自己の責任において、本サービスのユーザーIDおよびパスワードを適切に管理するものとします。

2. お客様は、いかなる場合にも、ユーザーIDおよびパスワードを第三者に譲渡または貸与し、もしくは第三者と共用することはできません。

3. 当社は、ユーザーIDとパスワードの組み合わせが登録情報と一致してログインされた場合には、そのユーザーIDを登録しているお客様自身による利用とみなします。

第5条(禁止事項)

お客様は、本サービスの利用にあたり、以下の行為をしてはなりません。

  • 法令または公序良俗に違反する行為
  • 犯罪行為に関連する行為
  • 本サービスの内容等、本サービスに含まれる著作権、商標権ほか知的財産権を侵害する行為
  • 当社、ほかのお客様、またはその他第三者のサーバーまたはネットワークの機能を破壊したり、妨害したりする行為
  • 本サービスによって得られた情報を商業的に利用する行為
  • 当社のサービスの運営を妨害するおそれのある行為
  • 不正アクセスをし、またはこれを試みる行為
  • 他のお客様に関する個人情報等を収集または蓄積する行為
  • 不正な目的を持って本サービスを利用する行為
  • 本サービスの他のお客様またはその他の第三者に不利益、損害、不快感を与える行為
  • 他のお客様に成りすます行為
  • 当社が許諾しない本サービス上での宣伝、広告、勧誘、または営業行為
  • 面識のない異性との出会いを目的とした行為
  • 当社のサービスに関連して、反社会的勢力に対して直接または間接に利益を供与する行為
  • その他、当社が不適切と判断する行為

制定日:2024年1月1日

最終改訂日:2026/9/10