MySQL 8.0 から デフォルトのパスワードの仕組みが caching_sha2_password
に変更されました。
これに関連して、yoku0825 さんが以下のエントリーを掲載してます。
yokuさんのエントリーを抜粋すると:
この条件にすべて合致しているとログインが転けて↑のエラーを食らう。
試します
挙動をおさらいします。
サーバ側で FLUSH PRIVILEGES
を実行しSHA2キャッシュをクリアしたあと、SSLを無効化して接続します。
確かに、Authentication requires secure connection.
とエラーが出て、接続できません。
$ mysql -uuser -h my8.local --ssl-mode=DISABLED ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
次に、--get-server-public-key
をつけます。このオプションはサーバの公開鍵を自動でクライアントに持ってくるオプションです。
サーバの公開鍵を使って、パスワードを暗号化し、サーバへ送信し、認証が行われます。
$ mysql -uuser -h my8.local --ssl-mode=DISABLED --get-server-public-key mysql>
一度、接続すれば、SHA2キャッシュが作られるので、以降は--get-server-public-key
を指定しなくても接続できるようになります。
$ mysql -uuser -h my8.local --ssl-mode=DISABLED mysql>
運用への影響を考えてみる
(サーバを再起動したりして) SHA2キャッシュがクリアされたときに、SSLを利用していないクライアントが一斉に接続エラーになっては困ります。 そのようなことが起こり得るか検討してみます。
mysql コマンド
mysql コマンドはデフォルトでSSLを利用します。あえてSSLを無効化しているようなケースはあまりないでしょう。 コマンドラインでMySQLを使っている場合は、心配しなくて良さそうです。
各種、言語ドライバーはどうでしょうか?
mysql コマンドの --get-server-public-key
相当の挙動がドライバ側に実装されていれば、開発者側では特に意識する必要はないということになりますが。。。
ドライバの挙動
PHP 7.4
PHP 7.4 で試します。
<?php try { $pdo = new PDO('mysql:host=my8.local;charset=utf8','user','Password%123'); } catch (PDOException $e) { exit($e->getMessage()); } $stmt = $pdo->query("SHOW STATUS LIKE 'Ssl_cipher'"); print_r($stmt->fetch(PDO::FETCH_ASSOC));
おっ、特にエラーなく接続できた!Ssl_cipherが空なのでSSL無効でエラーなく接続できました。
$ php pdo.php Array ( [Variable_name] => Ssl_cipher [Value] => )
PHP の コミットログをみると、きちんとサーバ側の公開鍵を自動で取ってくる実装が追加されていそうです👏
https://github.com/php/php-src/commit/d6e81f0bfd0cb90586dd83d4fd47a4302605261a
PHP7.3
PHP 7.3 でも試します。
$ php pdo.php SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client
そもそも、caching_sha2_password
がサポートされてないようですね 😢
MySQL 8 を使うには PHP7.4 以降を利用する必要があることがわかりました。
node.js
var mysql = require('mysql'); var con = mysql.createConnection({ host: "my8.local", user: "user", password: "Password%123" }); con.connect(function(err) { if (err) throw err; console.log("Connected!"); }); // simple query con.query( "SHOW STATUS LIKE 'Ssl_cipher'", function(err, results, fields) { console.log(results); } );
node.js の mysql もまだ caching_sha2_password
をサポートしてないようですね。。。。
$ node mysql.js /home/mita2/nodejs-conn/node_modules/mysql/lib/protocol/Parser.js:437 throw err; // Rethrow non-MySQL errors ^ Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
PRは出ているのですが、まだ、取り込まれてないようです。 https://github.com/mysqljs/mysql/pull/2233
mysql2 のほうには取り込まれているようなので、mysql2 を試します。
mysql
と mysql2
は互換性があります。ドライバを差し替えるにはvar mysql = require('mysql');
を var mysql = require('mysql2');
にするだけです。
$ node mysql.js Connected! [ TextRow { Variable_name: 'Ssl_cipher', Value: '' } ]
大丈夫そうです😄
まとめ
- PHPは 7.4 以上なら大丈夫!
- Node.js のドライバは mysql2 なら大丈夫!