MySQL | SQLite経験者向け、30日で習得するMySQL:実務応用 - Day27 権限管理

SQL MySQL
スポンサーリンク

Day27 前半のゴール

「“誰が何をしていいか”を、設計として説明できるようになる」

ここからは「権限管理」です。
パフォーマンスやAPI連携が「どう動かすか」だとしたら、権限管理は「誰にどこまで触らせるか」を決める話です。

前半のゴールはこうです。
認証と認可の違いを説明できるようになること。
ユーザー・ロール・権限という三層構造のイメージを持てること。
MySQLの権限と、アプリ側の権限を頭の中で分けて考えられること。

ここではまだSQLをガリガリ書かず、「考え方」と「モデル」を丁寧にかみ砕きます。


認証と認可をまず分けて考える

「“誰なのか”と“何をしていいか”は別の話」

権限管理の話をするとき、最初に必ず整理したいのが「認証」と「認可」です。

認証(Authentication)は、「あなたは誰ですか?」を確かめることです。
ログインIDとパスワード、トークン、OAuthなどは全部ここに属します。
「この人はユーザーID=123の本人だ」と確認するフェーズです。

認可(Authorization)は、「あなたは何をしていい人ですか?」を決めることです。
ユーザーID=123は、商品を閲覧していいのか、注文を作っていいのか、管理画面に入っていいのか。
ここが、まさに「権限管理」の領域です。

よくある失敗は、「ログインできたら何でもできる」状態にしてしまうことです。
ログインはスタートラインであって、「何をしていいか」は別途きちんと決める必要があります。


ユーザー・ロール・権限という三層モデル

「“人に直接権限をベタ付けしない”という発想」

権限管理を設計するときの定番パターンが、「ユーザー・ロール・権限」の三層モデルです。

ユーザーは「人」そのものです。
ロール(役割)は、「管理者」「一般ユーザー」「オペレーター」などの“役割ラベル”です。
権限(パーミッション)は、「商品を閲覧できる」「ユーザーを削除できる」といった“具体的な操作の許可”です。

ここで大事なのは、「ユーザーに直接権限をベタベタ付けない」ことです。
代わりに、こう考えます。

ユーザーはロールを持つ。
ロールは権限を持つ。

例えば、こんなイメージです。

一般ユーザー
→ 商品閲覧、注文作成、自分のプロフィール編集

管理者
→ 一般ユーザーの権限
→ さらにユーザー一覧閲覧、ユーザー情報編集、注文キャンセルなど

このように、「ロールに権限をまとめておき、ユーザーにはロールを割り当てる」ことで、
後から権限を変えたいときに「ロールの定義を変えるだけ」で済むようになります。


アプリ側の権限モデルをテーブルでイメージする

「users / roles / permissions / role_permissions / user_roles」

この三層モデルを、そのままDBのテーブルに落とすとどうなるかをイメージしてみます。

ユーザーを表す users テーブル。
ロールを表す roles テーブル。
権限を表す permissions テーブル。
ロールと権限の多対多をつなぐ role_permissions テーブル。
ユーザーとロールの多対多をつなぐ user_roles テーブル。

例えば、roles には「admin」「member」などの名前が入ります。
permissions には「view_products」「edit_users」「cancel_orders」などの“操作名”が入ります。
role_permissions で、「admin は edit_users を持つ」「member は view_products だけ持つ」といった対応関係を定義します。
user_roles で、「ユーザーID=1 は admin ロール」「ユーザーID=2 は member ロール」といった割り当てを持ちます。

こうしておくと、アプリ側では次のようなチェックができます。

ログインしたユーザーのIDから、そのユーザーのロール一覧を取得する。
ロール一覧から、そのユーザーが持つ権限一覧を取得する。
「このAPIを呼ぶには edit_users 権限が必要」と決めておき、権限一覧に含まれているかをチェックする。

これが、「アプリ側の権限管理」の基本的な考え方です。


MySQLの権限とアプリ側の権限は別物として考える

「“DBユーザーの権限”と“アプリユーザーの権限”を混ぜない」

ここで一つ、SQLite経験者が特につまずきやすいポイントがあります。
MySQL自体にも「ユーザー」と「権限」がある、ということです。

MySQLのユーザーは、CREATE USERGRANT で作る「DBユーザー」です。
例えば、「app_user は sample_app データベースに対して SELECT/INSERT/UPDATE だけできる」といった権限を設定できます。

一方、アプリ側のユーザー(ECサイトの会員など)は、users テーブルに入っている「アプリケーションユーザー」です。
この人たちの権限は、さっきの roles / permissions で管理します。

ここでやってはいけないのは、「アプリのユーザーごとに MySQL のユーザーを作る」ことです。
例えば、会員登録のたびに CREATE USER していたら、DB側のユーザー管理が破綻しますし、接続管理も地獄になります。

現実的な構成はこうです。

MySQL側には、「アプリ用のDBユーザー」を少数だけ作る(例:app_readonly、app_rw)。
アプリはそのDBユーザーで接続し、アプリ内部で「誰が何をしていいか」をロール・権限で制御する。

つまり、MySQLの権限は「アプリ全体としてDBに何をしていいか」を決めるレイヤー。
アプリ側の権限は「ログインユーザーごとに何をしていいか」を決めるレイヤー。
この二段構えで考えるのが、安全で現実的です。


「最小権限の原則」を権限管理の軸にする

「“できるだけ少なく”をデフォルトにする」

権限設計で一番大事な考え方が、「最小権限の原則(Least Privilege)」です。
これは、「そのユーザー(またはロール)が仕事をするのに必要な最小限の権限だけを与える」という考え方です。

例えば、ECサイトの一般ユーザーに「他人の注文をキャンセルする権限」は必要ありません。
管理画面のオペレーターに「DBのDROP TABLEを実行する権限」は必要ありません。
APIサーバーからDBに接続するユーザーに「全データベースへの全権限」は必要ありません。

最小権限の原則を守ると、もしアカウントが乗っ取られても、被害を限定できます。
逆に、「とりあえず全部許可」で設計してしまうと、一つの穴からシステム全体が崩壊します。

前半の段階では、「権限は“足りなければ足す”が基本で、“最初から盛りすぎない”」という感覚だけ、しっかり持っておいてください。


Day27 前半のまとめ

権限管理を考えるときは、まず「認証=誰かを確かめる」「認可=その人が何をしていいかを決める」という二段階を分けて捉え、そのうえでユーザー・ロール・権限という三層モデル(ユーザーはロールを持ち、ロールは権限を持つ)を使って、「人に直接権限をベタ付けするのではなく、役割ごとに権限をまとめておき、ユーザーには役割を割り当てる」という形にすることで、後からの変更や管理を楽にする。
さらに、MySQLのユーザー/権限は「アプリ全体としてDBに何をしていいか」を決めるレイヤー、アプリ側のユーザー/ロール/権限は「ログインユーザーごとに何をしていいか」を決めるレイヤーとして分けて考え、「最小権限の原則(必要最低限だけ許可する)」を軸に設計することが、Day27 後半で具体的なテーブル設計やGRANTの例、API側での権限チェックの実装に進むための土台になる。

タイトルとURLをコピーしました