今回から何回かに分けて、
今回のデモンストレーション環境はあえて
筆者が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 [email protected]; 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.
次々回では、