MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  アクセス制御、ステージ 1: 接続の検証

6.2.6 アクセス制御、ステージ 1: 接続の検証

MySQL サーバーに接続しようとすると、サーバーは次の条件に基づいて接続を受け入れるか拒否します:

  • アイデンティティ、および適切な資格証明を指定して検証できるかどうか。

  • アカウントがロックされているかロック解除されているか。

サーバーはまず資格証明をチェックし、次にアカウントのロック状態をチェックします。 いずれかのステップで障害が発生すると、サーバーはユーザーへのアクセスを完全に拒否します。 それ以外の場合、サーバーは接続を受け入れてステージ 2 に進み、リクエストを待機します。

サーバーは、user テーブルのカラムを使用してアイデンティティと資格証明のチェックを実行し、次の条件を満たしている場合にのみ接続を受け入れます:

  • クライアントホスト名およびユーザー名は、一部の user テーブルの行の Host および User のカラムと一致します。 Host および User の許容値を制御するルールについては、セクション6.2.4「アカウント名の指定」 を参照してください。

  • クライアントは、authentication_string カラムで示されるように、行で指定された資格証明 (パスワードなど) を提供します。 資格証明は、plugin カラムで指定された認証プラグインを使用して解釈されます。

  • 行は、アカウントがロック解除されていることを示します。 ロック状態は account_locked カラムに記録されます。このカラムの値は'N'である必要があります。 アカウントのロックは、CREATE USER ステートメントまたは ALTER USER ステートメントを使用して設定または変更できます。

ユーザーの ID は 2 つの部分の情報に基づきます。

  • MySQL ユーザー名

  • 接続元のクライアントホスト

User カラム値がブランクでない場合、入接続のユーザー名は正確に一致する必要があります。 User 値がブランクの場合、これはすべてのユーザー名と一致します。 入接続と一致する user テーブル行のユーザー名がブランクである場合、ユーザーはクライアントが実際に指定した名前を持つユーザーでなく、名前のない匿名ユーザーとみなされます。 つまり、接続期間中の (つまりステージ 2 での) 今後のすべてのアクセスチェックでブランクのユーザー名が使用されることを意味します。

authentication_string カラムは空白にできます。 これはワイルドカードではなく、あらゆるパスワードが一致するという意味ではありません。 これは、ユーザーはパスワードを指定せずに接続しなければならないことを意味します。 クライアントを認証するプラグインによって実装される認証方法は、authentication_string カラムのパスワードを使用する場合と使用しない場合があります。 この場合、MySQL サーバーへの認証を行う際に、外部パスワードも使用される可能性があります。

user テーブルの authentication_string カラムに格納されている空白以外のパスワード値は暗号化されます。 MySQL では、パスワードはクリアテキストとして格納されず、すべてのユーザーに表示されます。 かわりに、接続しようとしているユーザーが指定したパスワードは暗号化されます (アカウント認証プラグインによって実装されたパスワードハッシュ方式を使用)。 そのあと、暗号化パスワードは、接続プロセス中にパスワードが正しいかどうかをチェックするときに使用されます。 これは、暗号化パスワードが接続を介してやりとりされずに実行されます。 セクション6.2.1「アカウントのユーザー名とパスワード」を参照してください。

MySQL から見ると、暗号化パスワードが実際のパスワードであるため、暗号化パスワードへのアクセス権限をすべてのユーザーに付与しないようにしてください。 特に、mysql システムデータベース内のテーブルへの読取りアクセス権を非管理ユーザーに付与しない」です。

次のテーブルに、user テーブルの User 値と Host 値の様々な組合せが着信接続にどのように適用されるかを示します。

User Host 許容される接続
'fred' 'h1.example.net' fred, h1.example.net からの接続
'' 'h1.example.net' h1.example.net から接続する任意のユーザー
'fred' '%' 任意のホストから接続する fred
'' '%' 任意のホストから接続する任意のユーザー
'fred' '%.example.net' fred, example.net ドメインの任意のホストからの接続
'fred' 'x.example.%' fredx.example.net, x.example.com, x.example.edu からの接続など。これはおそらく役に立ちません
'fred' '198.51.100.177' IP アドレス 198.51.100.177 のホストから接続する fred
'fred' '198.51.100.%' 198.51.100 のクラス C サブネットの任意のホストから接続する fred
'fred' '198.51.100.0/255.255.255.0' 前の例と同じ

入接続のクライアントホスト名およびユーザー名が user テーブルの複数行と一致することもあります。 前述の一連の例は、これを示しています: 表示されるエントリのいくつかは、fred による h1.example.net からの接続と一致します。

複数の一致が可能な場合、サーバーはいずれを使用するかを決定する必要があります。 この問題は、次のように解決されます。

  • サーバーが user テーブルをメモリーに読み取るとき、行を毎回ソートします。

  • クライアントが接続しようとすると、サーバーは行をソート順に参照します。

  • サーバーは、クライアントホスト名およびユーザー名が一致した最初の行を使用します。

サーバーは、特定の Host 値が最も多い行から順に並べ替えるソートルールを使用します:

  • リテラル IP アドレスとホスト名は最も具体的です。

  • MySQL 8.0.23 より前は、リテラル IP アドレスの特異性はネットマスクがあるかどうかの影響を受けないため、198.51.100.13198.51.100.0/255.255.255.0 は同等とみなされます。 MySQL 8.0.23 の時点では、ホスト部分に IP アドレスを持つアカウントには次のような特異性があります:

    • ホスト部分が IP アドレスとして指定されているアカウント:

      CREATE USER 'user_name'@'127.0.0.1';
      CREATE USER 'user_name'@'198.51.100.44';
    • CIDR 表記を使用して IP アドレスとして指定されたホスト部分を持つアカウント:

      CREATE USER 'user_name'@'192.0.2.21/8';
      CREATE USER 'user_name'@'198.51.100.44/16';
    • ホスト部分が IP アドレスとしてサブネットマスクとともに指定されているアカウント:

      CREATE USER 'user_name'@'192.0.2.0/255.255.255.0';
      CREATE USER 'user_name'@'198.51.0.0/255.255.0.0';
  • パターン '%'任意のホストを意味するため、具体性はもっとも低くなります。

  • 空の文字列 ''任意のホストを意味しますが、'%' のあとにソートされます。

非 TCP (ソケットファイル、名前付きパイプおよび共有メモリー) 接続は、ローカル接続として扱われ、そのようなアカウントがある場合は localhost のホスト部分と照合され、そうでない場合は localhost と一致するワイルドカードを持つホスト部分と照合されます (たとえば、local%, l%, %)。

同じ Host 値を持つ行は、最も固有の User 値から順に並べられます。 空白の User 値は「任意のユーザー」を意味し、最も限定的ではないため、同じ Host 値を持つ行の場合、匿名でないユーザーは匿名ユーザーの前にソートされます。

HostUser の値が等しい行の場合、順序は非決定的です。

user テーブルが次の内容であると仮定して、これがどのように作用するかを説明します。

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

サーバーがテーブルをメモリーに読み取るとき、サーバーは前に記載したルールを使用して行をソートします。 ソート後の結果は次のようになります。

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

クライアントが接続しようとすると、サーバーはソート済みの行を参照し、見つかった最初の一致を使用します。 jeffrey による localhost からの接続の場合、テーブルの 2 つの行が一致し、すなわち Host および User 値が 'localhost' および '' であるものと、値が '%' および 'jeffrey' であるものが一致します。 ソート順では 'localhost' 行が最初になるため、サーバーはこの行を使用します。

次に別の例を示します。 user テーブルが次のようになっていると仮定します。

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| h1.example.net |          | ...
+----------------+----------+-

ソート済みテーブルは次のようになります。

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| h1.example.net |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

最初の行は h1.example.net の任意のユーザーによる接続と一致し、2 番目の行は任意のホストの jeffrey による接続と一致します。

注記

よくある誤解として、ある特定のユーザー名についてサーバーが接続に対する一致を検出しようとしたとき、そのユーザーの名前を明示的に指定するすべての行が最初に使用されるという認識があります。 これは正しくありません。 前述の例は、jeffrey による h1.example.net からの接続が、User カラム値として'jeffrey'を含む行ではなく、ユーザー名のない行によって最初に照合されることを示しています。 その結果、jeffrey は接続するときにユーザー名を指定したにもかかわらず、匿名ユーザーとして認証されます。

サーバーに接続できても権限が期待したものとは異なる場合、おそらくほかのアカウントとして認証されています。 サーバーがユーザーの認識に使用したアカウントを見つけるには、CURRENT_USER() 関数を使用します。 (セクション12.16「情報関数」を参照してください。) これは、一致する user テーブル行の User および Host 値を示す、user_name@host_name 形式の値を返します。 たとえば、jeffrey が接続して、次のクエリーを発行したとします。

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost     |
+----------------+

ここで表示された結果は、一致した user テーブル行の User カラム値がブランクであることを示しています。 つまり、サーバーは jeffrey を匿名ユーザーとして扱っています。

認証の問題を診断するための別の方法は、user テーブルを出力し、テーブルを手作業でソートして、最初の一致が行われた行を確認する方法です。


関連キーワード:  接続, パスワード, ユーザー, アカウント, サーバー, 認証, テーブル, user, 一致, User