はじめに
PHPのフレームワークであるLaravelを使ってWebアプリを開発しているときにエラーが出力されたので、原因と解決方法を残します。
事象
マイグレーションファイルを作成しマイグレートを実行したところ、以下のエラーが出力されました。
$ php artisan migrate
Illuminate\Database\QueryException : SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = laravel and table_name = migrations and table_type = 'BASE TABLE')
at /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
665| // If an exception occurs when attempting to run a query, we'll format the error
666| // message to include the bindings with SQL, which will make this exception a
667| // lot more helpful to the developer instead of just the database's errors.
668| catch (Exception $e) {
> 669| throw new QueryException(
670| $query, $this->prepareBindings($bindings), $e
671| );
672| }
673|
Exception trace:
1 PDOException::("PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]")
/Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
2 PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=laravel", "root", "secret", [])
/Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70
Please use the argument -v to see more details.
調査
まず、DB設定を確認してみます。.env
は以下のようになっています。
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=secret
実際にこの設定でMySQLに接続できるか試行してみます。
$ mysql -uroot -p -h 127.0.0.1 -P 3306
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 8.0.19 Homebrew
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| laravel |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
正常に接続でき、データベースも存在していることが確認できました。
原因
MySQLのバージョンが8.0.4以降の場合、デフォルトの認証方式がcaching_sha2_password
になっており、PHPのMySQL接続ライブラリがcaching_sha2_password
に対応していないため、MySQLに接続できない(ログインできない)というエラーが発生していました。
対処
認証方式をcaching_sha2_password
からmysql_native_password
に変更します。
まず、現在の認証方式を確認しておきます。
mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)
認証方式を変更するには以下を実行します。
mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'secret';
Query OK, 0 rows affected (0.01 sec)
mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)
恒久対処
新しいユーザーを作成するときのデフォルトの認証方式を設定します。
まず、デフォルトの認証方式を確認しておきます。
mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name | Value |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
1 row in set (0.02 sec)
デフォルトの認証方式を変更するには以下のように設定します。
※以下はmacOSにHomebrewでMySQLをインストールした場合の一例です。my.cnf
の場所は適宜読み替えてください。
$ vi /usr/local/etc/my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password
設定を変更したらMySQLを再起動します。
$ mysql.server stop
$ mysql.server start
もう一度設定を確認します。
mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name | Value |
+-------------------------------+-----------------------+
| default_authentication_plugin | mysql_native_password |
+-------------------------------+-----------------------+
1 row in set (0.00 sec)