MariaDBのmysql_native_password認証とは?基本からセキュリティ、代替まで徹底解説

2025-05-31

mysql_native_password は、MariaDB(およびMySQL)で最も古くから使われている認証プラグインの一つです。これは、ユーザーが提供したパスワードをハッシュ化して保存し、認証時にそのハッシュ値を使ってパスワードを検証する仕組みを提供します。

特徴と仕組み

  1. デフォルトの認証プラグイン(多くの場合): MariaDBでは、明示的に認証プラグインを指定せずにユーザーを作成した場合(CREATE USER ... IDENTIFIED BY 'password' のようにパスワードのみを指定した場合)、デフォルトで mysql_native_password が使用されることが多いです。特に old_passwords=0 が設定されている場合(これがデフォルトです)、このプラグインが使われます。

  2. パスワードハッシュ化: このプラグインは、パスワードをSHA-1ベースのハッシュアルゴリズムでハッシュ化して保存します。これはMySQL 4.1で導入されたパスワードハッシュアルゴリズムと同じものです。

  3. 互換性: 非常に多くのクライアントライブラリやアプリケーションがこの mysql_native_password に対応しています。これは、長年にわたってMySQL/MariaDBの標準的な認証方法であったためです。古いバージョンのPHPや他のクライアントがMariaDBに接続する際に、このプラグインが利用されることがよくあります。

セキュリティ上の考慮事項

mysql_native_password は広く使われていますが、最新のセキュリティ標準からすると、いくつかの懸念点があります。

  • 中間者攻撃のリスク: 悪意のある第三者が接続プロトコルを傍受し、mysql.user テーブルのコピーを入手できた場合、その情報を使ってMariaDBサーバーに接続できてしまう可能性があります。
  • SHA-1の脆弱性: SHA-1は、現在では暗号学的に安全とは見なされていません。理論上、総当たり攻撃や辞書攻撃によってパスワードが特定されるリスクがあります。

このような理由から、MariaDBの公式ドキュメントでは、高いパスワードセキュリティが求められる新しいインストールにおいて mysql_native_password の使用を推奨していません。

代替となるより安全な認証プラグイン

MariaDBでは、より強力なセキュリティを提供する他の認証プラグインが用意されています。

  • caching_sha2_password / sha256_password: これらはSHA-256ベースのハッシュアルゴリズムを使用し、mysql_native_password よりも強力です。MySQL 8.0では caching_sha2_password がデフォルトの認証プラグインになっています。
  • ed25519: これはMariaDB 10.2以降で利用可能な新しい認証プラグインで、より強力なハッシュアルゴリズム(EdDSAベースのEd25519)を使用します。OpenSSHでも使用されているアルゴリズムであり、より高いセキュリティを提供します。

ユーザーの作成とプラグインの指定例

mysql_native_password を使用してユーザーを作成する場合(通常はデフォルトでそうなることが多いですが、明示的に指定することも可能です):

-- old_passwordsが0であることを確認(デフォルト)
SET old_passwords=0;

-- パスワードのみ指定(デフォルトでmysql_native_passwordが使われる)
CREATE USER 'username'@'localhost' IDENTIFIED BY 'your_password';

-- 明示的にプラグインを指定
CREATE USER 'username'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('your_password');

よりセキュアな ed25519 を使用する場合:

CREATE USER 'username'@'localhost' IDENTIFIED VIA ed25519 USING PASSWORD('your_secure_password');


mysql_native_password はMariaDBで広く使われている認証プラグインですが、特にMySQLとの互換性や、より新しい認証方式への移行時に問題が発生することがあります。

エラーメッセージ: "Access denied for user 'username'@'hostname' (using password: NO)" または "Access denied for user 'username'@'hostname' (using password: YES)"

これは最も一般的な認証エラーです。

  • トラブルシューティング:

    1. ユーザー名とパスワードの確認: 正しいユーザー名とパスワードを使用しているか再確認してください。入力ミスがないか慎重に確認します。
    2. 接続元ホストの確認:
      • MariaDBサーバーにログインし(例: mysql -u root -p)、以下のクエリを実行して、ユーザーのホスト設定を確認します。
        SELECT user, host, plugin FROM mysql.user WHERE user = 'your_username';
        
      • もしhostlocalhostとなっている場合、そのユーザーはMariaDBサーバーと同じマシンからの接続しか許可していません。リモートからの接続を許可するには、%(任意のホスト)や特定のIPアドレスに変更する必要があります。
        -- ホストを更新する例 (既存ユーザーの場合)
        ALTER USER 'your_username'@'localhost' IDENTIFIED BY 'your_password'; -- まずパスワードを再設定してプラグインを更新
        ALTER USER 'your_username'@'%' IDENTIFIED BY 'your_password'; -- ホストを%に変更
        FLUSH PRIVILEGES; -- 権限の再読み込み
        
        または、新しいユーザーを適切なホストで作成します。
        CREATE USER 'your_username'@'%' IDENTIFIED BY 'your_password';
        GRANT ALL PRIVILEGES ON your_database.* TO 'your_username'@'%';
        FLUSH PRIVILEGES;
        
    3. 認証プラグインの確認と調整:
      • SELECT user, host, plugin FROM mysql.user WHERE user = 'your_username'; で、ユーザーに設定されているpluginが何かを確認します。
      • もしクライアントがmysql_native_passwordを期待しているのに、ユーザーがcaching_sha2_passworded25519など別のプラグインを使用している場合、以下のいずれかの対応が必要です。
        • ユーザーの認証プラグインをmysql_native_passwordに変更する:
          ALTER USER 'your_username'@'your_host' IDENTIFIED WITH mysql_native_password BY 'your_password';
          FLUSH PRIVILEGES;
          
          注意: これはセキュリティレベルを下げますが、古いクライアントとの互換性を確保するために必要となる場合があります。
        • クライアントが使用するドライバー/ライブラリを更新する: 多くのモダンなクライアントライブラリは、caching_sha2_passwordなどの新しい認証プラグインに対応しています。可能であれば、クライアント側を最新版に更新することを検討してください。
        • MariaDBサーバーのデフォルトプラグインを変更する: MariaDBの設定ファイル(my.cnfなど)で、デフォルトの認証プラグインをmysql_native_passwordに設定することも可能です。
          [mysqld]
          default_authentication_plugin=mysql_native_password
          
          この変更にはMariaDBサーバーの再起動が必要です。
  • 原因:

    • ユーザー名またはパスワードの誤り: 最も単純な原因です。
    • ホストからの接続が許可されていない: mysql.userテーブルのhostカラムに、接続元ホストからのアクセスが許可されていない場合に発生します。例えば、'user'@'localhost'として作成されたユーザーは、別のマシンからの接続を受け付けません。
    • ユーザーが存在しない: 指定されたユーザー名がデータベースに存在しません。
    • 認証プラグインの不一致: クライアントが期待する認証プラグインと、サーバー側でユーザーに設定されている認証プラグインが異なる場合に発生します。特に、MySQL 8.0以降がデフォルトでcaching_sha2_passwordを使用するようになったため、MariaDB(mysql_native_passwordがデフォルトの場合が多い)と混在する環境でよく見られます。
    • 権限不足: データベースへの接続自体は可能でも、アクセスしようとしているデータベースやテーブルに対する権限がない場合に発生します。

エラーメッセージ: "Plugin 'mysql_native_password' is not loaded"

これは、通常、MySQL 8.0以降で発生する可能性のあるエラーで、mysql_native_passwordプラグインがデフォルトでロードされていない、または完全に削除されている場合に起こります。MariaDBでは通常デフォルトで有効ですが、設定変更や非常に新しいMariaDBのバージョンで発生する可能性もゼロではありません。

  • トラブルシューティング:

    1. MariaDB設定ファイルの確認: my.cnf(またはmariadb.cnfなど)に以下の行を追加し、MariaDBサーバーを再起動します。
      [mysqld]
      plugin_load_add = mysql_native_password
      
      または、単にmysql_native_password=ONを設定します。
      [mysqld]
      mysql_native_password=ON
      
    2. (推奨)ユーザーの認証プラグインをより安全なものに変更する: 上記のエラーに遭遇した場合、それは古い認証方法を使用しているサインである可能性が高いです。可能であれば、ed25519caching_sha2_passwordなど、より強力な認証プラグインを使用するようにユーザーを変更し、クライアント側もそれに対応するように更新することを強く推奨します。
      ALTER USER 'your_username'@'your_host' IDENTIFIED WITH ed25519 BY 'your_new_password';
      FLUSH PRIVILEGES;
      
  • 原因:

    • MariaDBサーバーの設定でmysql_native_passwordプラグインがロードされていない。
    • (MySQLの場合)MySQL 8.0以降でmysql_native_passwordがデフォルトで無効になり、MySQL 9.0で完全に削除される予定のため。
    • 何らかの理由でプラグインファイルが破損している。

エラーメッセージ: "Client does not support authentication protocol requested by server"

  • トラブルシューティング:

    1. クライアントライブラリの更新: 最も推奨される解決策です。使用しているプログラミング言語のMySQL/MariaDBドライバーやODBCコネクタなどを最新バージョンに更新します。
    2. ユーザーの認証プラグインをmysql_native_passwordに戻す: クライアントライブラリの更新が難しい場合、ユーザーの認証プラグインをmysql_native_passwordに変更することで一時的に問題を解決できます。
      ALTER USER 'your_username'@'your_host' IDENTIFIED WITH mysql_native_password BY 'your_password';
      FLUSH PRIVILEGES;
      
      ただし、これはセキュリティレベルを低下させることに注意してください。
  • 原因:

    • クライアントライブラリが古く、サーバー側で設定されている新しい認証プラグイン(例: caching_sha2_passworded25519)に対応していない場合に発生します。

特定のアプリケーションからの接続問題

PHP、Java、Pythonなどの特定のアプリケーションからMariaDBに接続できない場合。

  • トラブルシューティング:

    1. 基本的な接続情報の確認: アプリケーションのDB接続設定が正しいことを確認します。
    2. 認証プラグインの確認: 上記「認証プラグインの不一致」の項を参照し、ユーザーの認証プラグインとクライアント(アプリケーション)が対応しているか確認・調整します。
    3. ファイアウォールの確認: MariaDBサーバー上で、ファイアウォール(firewalldiptablesなど)が3306番ポートへの接続を許可しているか確認します。
      # firewalldを使用している場合
      sudo firewall-cmd --list-all
      sudo firewall-cmd --add-port=3306/tcp --permanent
      sudo firewall-cmd --reload
      
      # iptablesを使用している場合
      sudo iptables -L -n
      # 3306番ポートを許可するルールを追加
      
    4. SELinuxの確認: SELinuxがEnforcingモードの場合、MySQL/MariaDBのプロセスがネットワークポートにバインドするのをブロックしたり、データディレクトリへのアクセスを制限したりすることがあります。
      • sestatus でSELinuxの状態を確認します。
      • ログ(/var/log/audit/audit.log など)にSELinux関連のエラーが出ていないか確認します。
      • SELinuxのルールを調整するか、一時的にPermissiveモードにすることで問題が解決するかをテストします(ただし、本番環境では適切にルールを設定すべきです)。
  • 原因:

    • 上記のような認証プラグインの不一致。
    • アプリケーションの設定ファイルで指定されたDB接続情報(ホスト名、ポート、ユーザー名、パスワード)が誤っている。
    • ファイアウォールやSELinuxなどのセキュリティ設定によって、DBポート(通常3306)への接続がブロックされている。


mysql_native_passwordはMariaDBの標準的な認証方式であり、特別な設定なしに多くのクライアントライブラリで動作します。そのため、以下のコード例は、認証プラグインを明示的に指定しなくても、通常はmysql_native_passwordを使用するように動作します。

前提条件:

  1. MariaDBサーバーの準備:
    • MariaDBサーバーが稼働していること。
    • 接続用のユーザーがmysql_native_passwordで認証するように設定されていること。 (多くの場合、CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password';のようにプラグインを明示しない場合は、デフォルトでmysql_native_passwordになります。)
    • 例として、以下のようなユーザーとデータベースを作成しておきます。
      CREATE DATABASE mydatabase;
      CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpassword';
      GRANT ALL PRIVILEGES ON mydatabase.* TO 'testuser'@'localhost';
      FLUSH PRIVILEGES;
      
      -- リモートからの接続を許可する場合 (注意: セキュリティリスクあり)
      -- CREATE USER 'testuser'@'%' IDENTIFIED BY 'testpassword';
      -- GRANT ALL PRIVILEGES ON mydatabase.* TO 'testuser'@'%';
      -- FLUSH PRIVILEGES;
      

Python (Python MariaDB Connectorを使用)

PythonからMariaDBに接続する場合、mariadbコネクタライブラリを使用するのが一般的です。

インストール: pip install mariadb

コード例:

import mariadb
import sys

# データベース接続情報
DB_CONFIG = {
    'host': 'localhost',
    'port': 3306,
    'user': 'testuser',
    'password': 'testpassword',
    'database': 'mydatabase'
}

try:
    # MariaDBに接続
    conn = mariadb.connect(
        host=DB_CONFIG['host'],
        port=DB_CONFIG['port'],
        user=DB_CONFIG['user'],
        password=DB_CONFIG['password'],
        database=DB_CONFIG['database']
    )
    print("MariaDBに正常に接続しました。")

    # カーソルオブジェクトの取得
    cur = conn.cursor()

    # テーブル作成(もし存在しなければ)
    try:
        cur.execute("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255))")
        print("テーブル 'users' を作成または確認しました。")
    except mariadb.Error as e:
        print(f"テーブル作成エラー: {e}")

    # データの挿入
    cur.execute("INSERT INTO users (name, email) VALUES (?, ?)", ("山田太郎", "[email protected]"))
    cur.execute("INSERT INTO users (name, email) VALUES (?, ?)", ("田中花子", "[email protected]"))
    conn.commit() # 変更をコミット
    print("データを挿入しました。")

    # データの取得
    cur.execute("SELECT id, name, email FROM users")
    print("\nユーザー情報:")
    for (id, name, email) in cur:
        print(f"ID: {id}, 名前: {name}, メール: {email}")

    # データの更新
    cur.execute("UPDATE users SET email = ? WHERE name = ?", ("[email protected]", "山田太郎"))
    conn.commit()
    print("\nデータを更新しました。")

    # 更新されたデータの確認
    cur.execute("SELECT id, name, email FROM users WHERE name = '山田太郎'")
    updated_user = cur.fetchone()
    if updated_user:
        print(f"更新後: ID: {updated_user[0]}, 名前: {updated_user[1]}, メール: {updated_user[2]}")

    # データの削除
    cur.execute("DELETE FROM users WHERE name = ?", ("田中花子",))
    conn.commit()
    print("\n田中花子のデータを削除しました。")

    # 残りのデータの確認
    cur.execute("SELECT id, name, email FROM users")
    print("\n残りのユーザー情報:")
    if cur.rowcount == 0:
        print("データがありません。")
    else:
        for (id, name, email) in cur:
            print(f"ID: {id}, 名前: {name}, メール: {email}")

except mariadb.Error as e:
    print(f"MariaDB接続エラー: {e}")
    sys.exit(1)
finally:
    # 接続を閉じる
    if 'conn' in locals() and conn:
        conn.close()
        print("\nMariaDB接続を閉じました。")

PHP

PHPからMariaDBに接続する場合、PDO (PHP Data Objects) または MySQLi 拡張機能を使用するのが一般的です。ここではPDOの例を示します。

コード例:

<?php

$host = 'localhost';
$db   = 'mydatabase';
$user = 'testuser';
$pass = 'testpassword';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
    echo "MariaDBに正常に接続しました。<br>";

    // テーブル作成(もし存在しなければ)
    $pdo->exec("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255))");
    echo "テーブル 'users' を作成または確認しました。<br>";

    // データの挿入
    $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
    $stmt->execute(["山田太郎", "[email protected]"]);
    $stmt->execute(["田中花子", "[email protected]"]);
    echo "データを挿入しました。<br>";

    // データの取得
    $stmt = $pdo->query("SELECT id, name, email FROM users");
    echo "<br>ユーザー情報:<br>";
    while ($row = $stmt->fetch()) {
        echo "ID: " . $row['id'] . ", 名前: " . $row['name'] . ", メール: " . $row['email'] . "<br>";
    }

    // データの更新
    $stmt = $pdo->prepare("UPDATE users SET email = ? WHERE name = ?");
    $stmt->execute(["[email protected]", "山田太郎"]);
    echo "<br>データを更新しました。<br>";

    // 更新されたデータの確認
    $stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE name = ?");
    $stmt->execute(["山田太郎"]);
    $updated_user = $stmt->fetch();
    if ($updated_user) {
        echo "更新後: ID: " . $updated_user['id'] . ", 名前: " . $updated_user['name'] . ", メール: " . $updated_user['email'] . "<br>";
    }

    // データの削除
    $stmt = $pdo->prepare("DELETE FROM users WHERE name = ?");
    $stmt->execute(["田中花子"]);
    echo "<br>田中花子のデータを削除しました。<br>";

    // 残りのデータの確認
    $stmt = $pdo->query("SELECT id, name, email FROM users");
    echo "<br>残りのユーザー情報:<br>";
    if ($stmt->rowCount() == 0) {
        echo "データがありません。<br>";
    } else {
        while ($row = $stmt->fetch()) {
            echo "ID: " . $row['id'] . ", 名前: " . $row['name'] . ", メール: " . $row['email'] . "<br>";
        }
    }

} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

?>

Node.js

Node.jsからMariaDBに接続する場合、mariadbパッケージを使用するのが公式の推奨方法です。

インストール: npm install mariadb

コード例:

const mariadb = require('mariadb');

// データベース接続プールを作成
const pool = mariadb.createPool({
    host: 'localhost',
    port: 3306,
    user: 'testuser',
    password: 'testpassword',
    database: 'mydatabase',
    connectionLimit: 5 // 同時接続の最大数
});

async function runQueries() {
    let conn;
    try {
        conn = await pool.getConnection();
        console.log("MariaDBに正常に接続しました。");

        // テーブル作成(もし存在しなければ)
        await conn.query("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255))");
        console.log("テーブル 'users' を作成または確認しました。");

        // データの挿入
        await conn.query("INSERT INTO users (name, email) VALUES (?, ?)", ["山田太郎", "[email protected]"]);
        await conn.query("INSERT INTO users (name, email) VALUES (?, ?)", ["田中花子", "[email protected]"]);
        console.log("データを挿入しました。");

        // データの取得
        const rows = await conn.query("SELECT id, name, email FROM users");
        console.log("\nユーザー情報:");
        rows.forEach(row => {
            console.log(`ID: ${row.id}, 名前: ${row.name}, メール: ${row.email}`);
        });

        // データの更新
        await conn.query("UPDATE users SET email = ? WHERE name = ?", ["[email protected]", "山田太郎"]);
        console.log("\nデータを更新しました。");

        // 更新されたデータの確認
        const updatedUser = await conn.query("SELECT id, name, email FROM users WHERE name = ?", ["山田太郎"]);
        if (updatedUser.length > 0) {
            console.log(`更新後: ID: ${updatedUser[0].id}, 名前: ${updatedUser[0].name}, メール: ${updatedUser[0].email}`);
        }

        // データの削除
        await conn.query("DELETE FROM users WHERE name = ?", ["田中花子"]);
        console.log("\n田中花子のデータを削除しました。");

        // 残りのデータの確認
        const remainingRows = await conn.query("SELECT id, name, email FROM users");
        console.log("\n残りのユーザー情報:");
        if (remainingRows.length === 0) {
            console.log("データがありません。");
        } else {
            remainingRows.forEach(row => {
                console.log(`ID: ${row.id}, 名前: ${row.name}, メール: ${row.email}`);
            });
        }

    } catch (err) {
        console.error(`MariaDB接続またはクエリ実行エラー: ${err}`);
    } finally {
        if (conn) {
            conn.release(); // 接続をプールに解放
            console.log("\nMariaDB接続をプールに解放しました。");
        }
        await pool.end(); // プールを閉じる (スクリプトの最後で一度だけ実行)
        console.log("MariaDB接続プールを閉じました。");
    }
}

runQueries();

JavaからMariaDBに接続する場合、MariaDB Connector/Jを使用します。MavenやGradleプロジェクトであれば、pom.xmlbuild.gradleに依存関係を追加します。

Mavenの場合の依存関係:

<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>3.3.3</version> </dependency>

コード例:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class MariaDbNativePasswordExample {

    private static final String DB_URL = "jdbc:mariadb://localhost:3306/mydatabase";
    private static final String DB_USER = "testuser";
    private static final String DB_PASSWORD = "testpassword";

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            // MariaDBドライバーのロード (JDBC 4.0以降は不要な場合が多いが、明示的に記述)
            Class.forName("org.mariadb.jdbc.Driver");

            // MariaDBに接続
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            System.out.println("MariaDBに正常に接続しました。");

            // テーブル作成(もし存在しなければ)
            stmt = conn.createStatement();
            stmt.executeUpdate("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255))");
            System.out.println("テーブル 'users' を作成または確認しました。");

            // データの挿入
            pstmt = conn.prepareStatement("INSERT INTO users (name, email) VALUES (?, ?)");
            pstmt.setString(1, "山田太郎");
            pstmt.setString(2, "[email protected]");
            pstmt.executeUpdate();

            pstmt.setString(1, "田中花子");
            pstmt.setString(2, "[email protected]");
            pstmt.executeUpdate();
            System.out.println("データを挿入しました。");

            // データの取得
            rs = stmt.executeQuery("SELECT id, name, email FROM users");
            System.out.println("\nユーザー情報:");
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.printf("ID: %d, 名前: %s, メール: %s%n", id, name, email);
            }

            // データの更新
            pstmt = conn.prepareStatement("UPDATE users SET email = ? WHERE name = ?");
            pstmt.setString(1, "[email protected]");
            pstmt.setString(2, "山田太郎");
            pstmt.executeUpdate();
            System.out.println("\nデータを更新しました。");

            // 更新されたデータの確認
            pstmt = conn.prepareStatement("SELECT id, name, email FROM users WHERE name = ?");
            pstmt.setString(1, "山田太郎");
            rs = pstmt.executeQuery();
            if (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.printf("更新後: ID: %d, 名前: %s, メール: %s%n", id, name, email);
            }

            // データの削除
            pstmt = conn.prepareStatement("DELETE FROM users WHERE name = ?");
            pstmt.setString(1, "田中花子");
            pstmt.executeUpdate();
            System.out.println("\n田中花子のデータを削除しました。");

            // 残りのデータの確認
            rs = stmt.executeQuery("SELECT id, name, email FROM users");
            System.out.println("\n残りのユーザー情報:");
            if (!rs.isBeforeFirst()) { // 結果セットが空かどうかを確認
                System.out.println("データがありません。");
            } else {
                while (rs.next()) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    String email = rs.getString("email");
                    System.out.printf("ID: %d, 名前: %s, メール: %s%n", id, name, email);
                }
            }

        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // リソースのクローズ (逆順が推奨)
            try {
                if (rs != null) rs.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
            try {
                if (pstmt != null) pstmt.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
            try {
                if (conn != null) conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
            System.out.println("\nMariaDB接続を閉じました。");
        }
    }
}


ed25519 (推奨されるモダンな認証プラグイン)

MariaDB 10.2以降で導入されたed25519は、EdDSA (Edwards-curve Digital Signature Algorithm) ベースの暗号アルゴリズムを使用しており、mysql_native_passwordよりもはるかに強力で安全です。OpenSSHなどでも採用されている方式です。

サーバー側の設定 (ユーザー作成):

CREATE USER 'secureuser'@'localhost' IDENTIFIED VIA ed25519 USING PASSWORD('your_strong_password');
GRANT ALL PRIVILEGES ON mydatabase.* TO 'secureuser'@'localhost';
FLUSH PRIVILEGES;

プログラミング例:

クライアントライブラリがed25519に対応している場合、接続コード自体はmysql_native_passwordの場合とほとんど変わりません。ライブラリが自動的にサーバーからの認証要求(この場合はed25519)を処理します。

  • PHP (PDO): PHPのPDO mysql ドライバーは、MariaDBのed25519認証プラグインに直接対応していない場合があります。このような場合、接続はmysql_native_passwordにフォールバックしようとするか、認証エラーが発生する可能性があります。完全にed25519を使用するには、MariaDBの専用PHPコネクタ (php-mariadb) の使用を検討するか、サーバー側でmysql_native_passwordも許可する複合認証を設定する必要があるかもしれません。

    • 備考: MariaDBの公式ドキュメントによると、ed25519はクライアントサイドでもclient_ed25519というプラグインを必要とします。多くの一般的な言語の組み込みドライバーでは、このクライアントサイドプラグインがデフォルトでバンドルされていない場合があります。
  • Python (MariaDB Connector): 最新バージョンのmariadbコネクタはed25519に対応しています。

    import mariadb
    import sys
    
    DB_CONFIG = {
        'host': 'localhost',
        'port': 3306,
        'user': 'secureuser', # ed25519で認証するユーザー
        'password': 'your_strong_password',
        'database': 'mydatabase'
    }
    
    try:
        conn = mariadb.connect(**DB_CONFIG)
        print("MariaDB (ed25519認証) に正常に接続しました。")
        # 以降のDB操作はmysql_native_passwordの場合と同じ
        cur = conn.cursor()
        cur.execute("SELECT 1")
        print("クエリ実行成功")
    except mariadb.Error as e:
        print(f"MariaDB接続エラー: {e}")
        sys.exit(1)
    finally:
        if 'conn' in locals() and conn:
            conn.close()
    

caching_sha2_password (MySQL 8.0のデフォルトプラグイン)

これはMySQL 8.0でデフォルトになった認証プラグインで、SHA-256ハッシュアルゴリズムと認証キャッシュを使用します。MariaDBは直接このプラグインをサポートしていませんが、互換性のあるクライアントサイドプラグインを提供している場合があります。

サーバー側の設定 (ユーザー作成): MariaDBサーバーは、直接caching_sha2_passwordをサポートしていません。しかし、もしMariaDBサーバーでMySQL 8.0と互換性のあるクライアントからの接続を受け入れたい場合、MariaDBではmysql_native_passwordを使い続けるか、あるいはed25519のような別の強力なプラグインを導入するのが一般的です。

プログラミング例:

  • Python (MySQL Connector/Python): MySQL 8.0と接続する場合は、このコネクタがcaching_sha2_passwordにデフォルトで対応しています。
    import mysql.connector # pip install mysql-connector-python
    import sys
    
    DB_CONFIG = {
        'host': 'localhost',
        'port': 3306,
        'user': 'my8user', # MySQL 8.0でcaching_sha2_passwordで認証するユーザー
        'password': 'my8password',
        'database': 'mydatabase'
    }
    
    try:
        # MySQL 8.0にcaching_sha2_passwordで認証する
        conn = mysql.connector.connect(**DB_CONFIG)
        print("MySQL 8.0 (caching_sha2_password認証) に正常に接続しました。")
        cur = conn.cursor()
        cur.execute("SELECT VERSION()")
        version = cur.fetchone()[0]
        print(f"接続バージョン: {version}")
    except mysql.connector.Error as e:
        print(f"MySQL接続エラー: {e}")
        sys.exit(1)
    finally:
        if 'conn' in locals() and conn:
            conn.close()
    
    注意: 上記はMySQL 8.0への接続例であり、MariaDBサーバーがcaching_sha2_passwordを直接サポートしているわけではありません。MariaDBでこの認証を使いたい場合は、互換性レイヤーやプロキシ(MariaDB MaxScaleなど)を考慮する必要があります。

unix_socket (Unix系OSのローカル接続向け)

unix_socket認証は、Unix系OSにおいて、MariaDBサーバーと同じマシンから接続する場合に非常に便利で安全な認証方法です。パスワードがネットワーク上を流れることがなく、OSのユーザー認証と紐付けられます。

サーバー側の設定 (ユーザー作成):

CREATE USER 'root'@'localhost' IDENTIFIED VIA unix_socket;
-- または
CREATE USER 'localuser'@'localhost' IDENTIFIED VIA unix_socket;
-- 特定のOSユーザーにマップする場合 (例: OSユーザー 'web_app' でMariaDBユーザー 'localuser' に接続)
-- CREATE USER 'localuser'@'localhost' IDENTIFIED VIA unix_socket AS 'web_app';
FLUSH PRIVILEGES;

この設定では、rootユーザー(またはlocaluser)がMariaDBサーバーと同じマシン上で、対応するOSのユーザーとしてログインしている場合にのみ、パスワードなしで接続できます。

プログラミング例:

通常、接続文字列でソケットファイルを指定するだけで、クライアントライブラリがunix_socket認証を自動的に試みます。

  • PHP (PDO):

    <?php
    
    $socket = '/var/run/mysqld/mysqld.sock';
    $db     = 'mydatabase';
    $user   = 'root'; // unix_socketで認証するユーザー
    
    // DSNでunix_socketを指定
    $dsn = "mysql:unix_socket=$socket;dbname=$db;charset=utf8mb4";
    $options = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    
    try {
        $pdo = new PDO($dsn, $user, null, $options); // unix_socketの場合、パスワードはnull
        echo "MariaDB (Unix Socket認証) に正常に接続しました。<br>";
    
        $stmt = $pdo->query("SELECT CURRENT_USER()");
        $row = $stmt->fetch();
        echo "接続ユーザー: " . $row['CURRENT_USER()'] . "<br>";
    
    } catch (\PDOException $e) {
        echo "MariaDB接続エラー: " . $e->getMessage() . "<br>";
    }
    
    ?>
    
  • Python (MariaDB Connector):

    import mariadb
    import sys
    
    # Unixソケットファイルのパス (MariaDBの設定による、多くは/var/run/mysqld/mysqld.sock)
    SOCKET_PATH = '/var/run/mysqld/mysqld.sock' 
    
    DB_CONFIG_SOCKET = {
        'unix_socket': SOCKET_PATH,
        'user': 'root', # unix_socketで認証するユーザー (OSユーザーと一致する必要がある)
        'database': 'mydatabase'
    }
    
    try:
        # unix_socketを使用してMariaDBに接続
        conn = mariadb.connect(**DB_CONFIG_SOCKET)
        print("MariaDB (Unix Socket認証) に正常に接続しました。")
        cur = conn.cursor()
        cur.execute("SELECT CURRENT_USER()")
        current_user = cur.fetchone()[0]
        print(f"接続ユーザー: {current_user}")
    except mariadb.Error as e:
        print(f"MariaDB接続エラー: {e}")
        sys.exit(1)
    finally:
        if 'conn' in locals() and conn:
            conn.close()
    

gssapi (Kerberos/GSSAPI認証)

大規模なエンタープライズ環境で、Active DirectoryやKerberosサーバーとの統合が必要な場合に利用されます。設定は複雑になりますが、集中管理された認証インフラストラクチャにMariaDBを組み込むことができます。

プログラミング例:

gssapi認証は通常、特別なクライアント設定やライブラリのサポートが必要です。一般的な用途ではあまり使われませんが、例えばJavaではKerberosの設定(krb5.confなど)とJDBC接続プロパティでGSSAPIを指定することで利用可能になります。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class MariaDbGssapiExample {

    // Kerberos/GSSAPIの設定に依存
    private static final String DB_URL = "jdbc:mariadb://hostname:3306/mydatabase";
    private static final String DB_USER = "kerberos_principal@REALM"; // 例: mariadb/server.example.com@MYREALM

    public static void main(String[] args) {
        Connection conn = null;
        try {
            // JVMのKerberos設定 (例: -Djava.security.krb5.conf=/etc/krb5.conf) が必要
            // JDBC URLに認証プラグインを指定するプロパティを追加する場合もある
            // 例: jdbc:mariadb://hostname:3306/mydatabase?authenticationPlugins=auth_gssapi_client
            conn = DriverManager.getConnection(DB_URL, DB_USER, ""); // GSSAPIではパスワードは不要

            System.out.println("MariaDB (GSSAPI認証) に正常に接続しました。");
            // ... データベース操作 ...

        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }
}

注意: GSSAPI認証は、クライアントとサーバーの両方でKerberos設定と適切なプラグインが有効になっている必要があります。

mysql_native_passwordは互換性が高い反面、セキュリティ上の懸念があります。新規開発やセキュリティが重視されるシステムでは、より強力な認証プラグインの利用を検討すべきです。

  • caching_sha2_password: MySQL 8.0との互換性が必要な場合に検討されますが、MariaDBサーバーが直接サポートしているわけではありません。
  • unix_socket: ローカル接続限定で非常に安全。サーバーとアプリケーションが同じマシンで動く場合に最適です。
  • ed25519: MariaDBの推奨する最新かつ強力な認証プラグイン。可能な限りこれを使用すべきです。クライアントライブラリがこれに対応しているか確認が必要です。