【Python x MySQL】 Authentication plugin 'caching_sha2_password' is not supportedエラーの解決方法

# 概要
- PythonからMySQLに接続しようとしたら、`'caching_sha2_password' is not supported`エラーが表示されました。
- 本記事ではこちらの解決方法を記します。

# エラー内容
```
mysql.connector.errors.NotSupportedError: Authentication plugin 'caching_sha2_password' is not supported
```

- `caching_sha2_password`いう認証プラグインがサポートされていないことを示しているよう。

## `caching_sha2_password`とは
- `mysql_native_password`：MySQL 8.0以前のバージョンで、デフォルトの認証プラグイン。パスワードはハッシュ化されず、平文のままデータベースに保存される。
- `caching_sha2_password`：MySQL 8.0以降で導入された新しいデフォルトの認証プラグイン。パスワードはSHA-256ハッシュ関数とソルトを使用してパスワードをハッシュ化され、データベースに保存される。

### mysql.connector (mysql-connector-python) とは
- PythonとMySQLサーバとの接続を提供するための公式のMySQLコネクタです。
- 通常、`mysql.connector`モジュールは`mysql-connector-python`パッケージに含まれています。

# 原因の模索
- まずは以下のサイトを参考にしました。
    - [mysql.connector で Authentication plugin ‘caching_sha2_password’ is not supported のエラー](https://isgs-lab.com/613/)

> MySQL 8.0以降、認証方式のデフォルトがそのcaching_sha2_passwordに変更されているが、mysql.connectorがそれにまだ対応していないため。


- なるほど、なので認証方式を従来の`mysql_native_password`に戻してあげようということ。（上記記事では、Pythonプログラムから接続するユーザーのみの最小限で設定変更する、という方針だったのでそれで実施）

```
mysql -u root -p
```

```
alter user 'root'@'%' identified with mysql_native_password by 'yourpassword';
```

- 以下で設定が反映されているか確認できます。

```
mysql> select user, plugin from mysql.user where user='root';
+------+-----------------------+
| user | plugin                |
+------+-----------------------+
| root | mysql_native_password |
| root | mysql_native_password |
+------+-----------------------+
```

- これで直るはず、と思ったら、、また同じエラーが出ました。あれ。上記記事に`auth_plugin`パラメーターで明示的に設定したら解決したとあったのですが、自分はやってみても変わらず...

```python
conn = mysql.connector.connect(
    host="yourhost",
    port=3306,
    user="yourname",
    password="yourpassword",
    database="yourdb",
    auth_plugin="mysql_native_password"
)
```

- MySQLサーバーの設定ファイル`my.cnf`(もしくは`my.ini`)でデフォルトの認証プラグインの設定ができるので編集してみる。
- ここを変更すると古い認証プラグインである`mysql_native_password`が使用できるはずです(デフォルトではコメントアウトされていました) 。

```my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password
```

- しかし、まだ同じエラー。なぬw

# 解決方法
- ググっていると以下サイトを発見。
    - [mysql connector errors NotSupportedError Authentication plugin caching sha2 password is not supported](https://www.edureka.co/community/77401/connector-notsupportederror-authentication-password-supported)

> Yeah., pip install mysql-connector-python worked!!!

- 自分が`pip install`していたのは`mysql.connector`でした。
- ということで、上記サイトの通り、以下のコマンドを実施。

```
pip install --upgrade mysql-connector-python
```

- すると...解決！
- `mysql-connector-python`パッケージのバージョンを最新のものにアップデートすることで、問題が解決しました。
- 今回インストールして利用していたモジュール`mysql.connector`のバージョン？にサポートされていないために発生していたと考えられます。
- 公式ドキュメント：
    - [6.4.1.2 SHA-2 プラガブル認証のキャッシュ](https://dev.mysql.com/doc/refman/8.0/ja/caching-sha2-pluggable-authentication.html)
    - [優先認証プラグインとしての caching_sha2_password](https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html#upgrade-caching-sha2-password)

> MySQL 8.0 では、caching_sha2_password が mysql_native_password ではなくデフォルトの認証プラグインです。 

> caching_sha2_password および sha256_password 認証プラグインは、mysql_native_password プラグインよりもセキュアなパスワード暗号化を提供し、caching_sha2_password は sha256_password よりも優れたパフォーマンスを提供します。 

- ちなみに、上述した`mysqld`のデフォルト認証プラグイン設定のところは後でリセットしておきましたが問題なかったです。こちらも上記公式ドキュメントに記載がありますが、「8.0 より前のクライアントが 8.0 サーバーに接続できるよう」にするための設定です。ただし、一時的なものとして使用するものであり、セキュリティ的には新しい方が良いみたいです。

> MySQL インストールで 8.0 より前のクライアントを提供する必要があり、MySQL 8.0 以上へのアップグレード後に互換性の問題が発生した場合、これらの問題に対処して 8.0 より前の互換性をリストアする最も簡単な方法は、以前のデフォルトの認証プラグイン (mysql_native_password) に戻すようにサーバーを再構成することです。