今回から何回かに分けて、
今回のデモンストレーション環境はあえて
筆者がCentOS 6.
$ sudo yum install -y http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm $ sudo yum install -y --disablerepo=mysql57-community --enablerepo=mysql56-community mysql-community-server $ sudo service mysqld start
MySQLのユーザー情報の格納先
MySQLにログインするためのアカウント情報は、mysqldのメモリ上に展開されています。またアカウント情報の本体とは別に、mysqlスキーマのuserテーブルに1ユーザー1レコードとしてスナップショットが永続化されていますmysql.=アカウント情報の実体、
筆者が今回の環境として用意したMySQLサーバーを起動した直後の状態です
$ mysql -uroot mysql> SELECT user, host FROM mysql.user; +------+-----------+ | user | host | +------+-----------+ | root | 127.0.0.1 | | root | ::1 | | | centos | | root | centos | | | localhost | | root | localhost | +------+-----------+ 6 rows in set (0.00 sec)
mysqlスキーマのuserテーブルにはこの他にもたくさんのカラムがあります。少し長くなりますが、DESCRIBEステートメントでカラムの情報を表示してみましょう。
mysql> DESCRIBE mysql.user;
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Host | char(60) | NO | PRI | | |
| User | char(16) | NO | PRI | | |
| Password | char(41) | NO | | | |
| Select_priv | enum('N','Y') | NO | | N | |
| Insert_priv | enum('N','Y') | NO | | N | |
| Update_priv | enum('N','Y') | NO | | N | |
| Delete_priv | enum('N','Y') | NO | | N | |
| Create_priv | enum('N','Y') | NO | | N | |
| Drop_priv | enum('N','Y') | NO | | N | |
| Reload_priv | enum('N','Y') | NO | | N | |
| Shutdown_priv | enum('N','Y') | NO | | N | |
| Process_priv | enum('N','Y') | NO | | N | |
| File_priv | enum('N','Y') | NO | | N | |
| Grant_priv | enum('N','Y') | NO | | N | |
| References_priv | enum('N','Y') | NO | | N | |
| Index_priv | enum('N','Y') | NO | | N | |
| Alter_priv | enum('N','Y') | NO | | N | |
| Show_db_priv | enum('N','Y') | NO | | N | |
| Super_priv | enum('N','Y') | NO | | N | |
| Create_tmp_table_priv | enum('N','Y') | NO | | N | |
| Lock_tables_priv | enum('N','Y') | NO | | N | |
| Execute_priv | enum('N','Y') | NO | | N | |
| Repl_slave_priv | enum('N','Y') | NO | | N | |
| Repl_client_priv | enum('N','Y') | NO | | N | |
| Create_view_priv | enum('N','Y') | NO | | N | |
| Show_view_priv | enum('N','Y') | NO | | N | |
| Create_routine_priv | enum('N','Y') | NO | | N | |
| Alter_routine_priv | enum('N','Y') | NO | | N | |
| Create_user_priv | enum('N','Y') | NO | | N | |
| Event_priv | enum('N','Y') | NO | | N | |
| Trigger_priv | enum('N','Y') | NO | | N | |
| Create_tablespace_priv | enum('N','Y') | NO | | N | |
| ssl_type | enum('','ANY','X509','SPECIFIED') | NO | | | |
| ssl_cipher | blob | NO | | NULL | |
| x509_issuer | blob | NO | | NULL | |
| x509_subject | blob | NO | | NULL | |
| max_questions | int(11) unsigned | NO | | 0 | |
| max_updates | int(11) unsigned | NO | | 0 | |
| max_connections | int(11) unsigned | NO | | 0 | |
| max_user_connections | int(11) unsigned | NO | | 0 | |
| plugin | char(64) | YES | | mysql_native_password | |
| authentication_string | text | YES | | NULL | |
| password_expired | enum('N','Y') | NO | | N | |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
43 rows in set (0.00 sec)
HostカラムとUserカラムが複合プライマリキーとして定義されています。これはMySQLではHostに該当する部分をUserに該当する部分を(Host, User)で識別される部分を
「rootユーザーのTCP経由の接続である root@127.
Hostカラムはchar(64)、Userカラムはchar(16)char(32)に拡張されました)
Passwordカラムauthentication_カラムに変更され、Passwordカラムは削除されました。MySQL 5.authentication_カラムは存在しますが利用されていません
*_privカラムにはユーザーのグローバル権限GRANTステートメント上で許可する対象を*.*で指定したもの)GRANT SELECT, INSERT ON *.* TO ..でアカウントに権限を設定した場合、Select_とInsert_が'Y'に設定されます。
その他GRANTステートメントで指定することのできるアカウント単位の属性GRANTステートメントで指定可能なアカウント単位の属性の詳細はリファレンスマニュアルを参照してください)。
MySQLのユーザー認証の仕組み
MySQLへのログイン試行は、
- 接続元ホストの検証
- アカウントの検証
- パスワードの検証
1.で行われる検証の内容は、
mysql> SELECT EXISTS (SELECT host FROM mysql.user WHERE host= 'localhost'); +--------------------------------------------------------------+ | EXISTS (SELECT host FROM mysql.user WHERE host= 'localhost') | +--------------------------------------------------------------+ | 1 | +--------------------------------------------------------------+ 1 row in set (0.03 sec) mysql> SELECT EXISTS (SELECT host FROM mysql.user WHERE host= '172.17.42.1'); +----------------------------------------------------------------+ | EXISTS (SELECT host FROM mysql.user WHERE host= '192.168.0.1') | +----------------------------------------------------------------+ | 0 | +----------------------------------------------------------------+ 1 row in set (0.00 sec)
接続元ホストがそもそもmysql.に登録されているかどうかが判定されます。接続元ホストが登録されておりユーザーやパスワードが違った場合には ER_
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) ERROR 1130 (HY000): Host '172.17.42.1' is not allowed to connect to this MySQL server
2.で行われる検証の内容は次のSQLステートメントにたとえることができます。
mysql> SELECT EXISTS(SELECT user FROM mysql.user WHERE (host, user)= ('127.0.0.1', 'root'));
+-------------------------------------------------------------------------------+
| EXISTS(SELECT user FROM mysql.user WHERE (host, user)= ('127.0.0.1', 'root')) |
+-------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------+
1 row in set (0.00 sec)
接続元ホスト、
3.で行われるパスワードの検証方法はプラグインで制御することが可能です。MySQL 4.mysql_認証プラグインが有効になっており、mysql_認証プラグイン、mysql_認証プラグインなどがあります
アカウント情報と mysql.user テーブルの同期
MySQLはmysqldのメモリ上にアカウント情報を持ち、mysql.テーブルはアカウント情報のスナップショットであり、mysql.テーブルをロードしてメモリ上にアカウント情報を展開します。
CREATE USERステートメントやGRANTステートメント、DROP USERステートメント、REVOKEステートメントなどは、mysql.テーブルを同時に変更」mysql.テーブルの内容は同じものになるケースがほとんどですが、mysql.テーブルを直接編集した場合はこれらに差異が生じることになります。そして、mysqlスキーマを含めたmysqldumpからデータベースをリストアした場合に、
メモリ上のアカウント情報は 「mysqldの(再)起動」FLUSH PRIVILEGESステートメント」SHOW GRANTSステートメントが追加したアカウントを認識しない」FLUSH PRIVILEGESステートメントを試してみてください。
mysql> SELECT EXISTS(SELECT user FROM mysql.user WHERE (host, user)= ('127.0.0.1', 'yoku0825'));
+-----------------------------------------------------------------------------------+
| EXISTS(SELECT user FROM mysql.user WHERE (host, user)= ('127.0.0.1', 'yoku0825')) |
+-----------------------------------------------------------------------------------+
| 1 |
+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SHOW GRANTS FOR yoku0825@127.0.0.1;
ERROR 1141 (42000): There is no such grant defined for user 'yoku0825' on host '127.0.0.1'
まとめ
MySQLのアカウント情報はmysqldのメモリ上とmysql.テーブルに保管されます。実際に認証に利用されるのはメモリ上のアカウント情報であり、mysql.はmysqldの起動時及びFLUSH PRIVILEGESステートメントの実行時にアカウント情報を再構築するためのデータストアです。
ログイン試行は
今回説明した内容の詳細はMySQL :: MySQL 5.
次々回では、
