🌊

ID/passwordによる認証 > 一番初めの認証(使用禁止)

2021/08/16に公開

目次ページ https://zenn.dev/gallu/articles/05335420b8e585

前提

ID/passwordによる認証の、「一番初期に考える」実装です。
なお「洒落にならないレベルで脆弱」なので、この実装は「しないでください」。

解説

比較的簡単な「IDとパスワードによる認証」で、多分一番初めに出てきそうな実装、ですが、「平文でパスワードを保存する」とか、絶対にやっては駄目な実装なので「間違っても絶対に何が何でもやらない」ようにしましょう。

想定するテーブルレイアウト

CREATE TABLE `ログインアカウント` (
  `login_id` varbinary(256) NOT NULL COMMENT 'ログインID',
  `password` varbinary(256) NOT NULL COMMENT 'パスワード',
  PRIMARY KEY (`login_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='1レコードが「(1ユーザの)ログイン情報」なテーブル'

実装

入力は一端、 $_POST['login_id']$_POST['password'] で取得可能である、とします。
また、DBハンドルは $dbh にすでに(PDOインスタンスが)入っているもの、とします。
実装方法としては
・login_idでレコードを検索、パスワードを文字列比較
・login_idとパスワードでレコードを検索
のどちらでも動きます。

実装例(login_idとパスワードでレコードを検索、のパターン)

class Authentication
{
    /**
     * 認証処理本体
     *
     * @param string $login_id ログインID
     * @param string $password ログインパスワード
     * @return array|null 認証の可否(arrayなら認証成功、nullなら認証失敗)
     */
    public static function login(string $login_id, string $password) : ?array
    {
        // ごく最低限のvalidate
        if ( ('' === $id)||('' === $password) ) {
            // ログイン失敗
            return null;
        }

        // プリペアドステートメントの作成
        $pre = $dbh->prepare('SELECT * FROM ログインアカウント WHERE login_id=:login_id AND password=:password;');
        // 値のバインド
        $pre->bindValue(':login_id', $login_id);
        $pre->bindValue(':password', $password);
        // SQLの実行
        $r = $pre->execute();
        // レコードの取得
        $account = $pre->fetch( \PDO::FETCH_ASSOC );

        // レコードが空なら
        if (false === $account) {
            // ログイン失敗
            return null;
        }
        
        // ログイン成功
        return $account;
    }
}

// ログイン
$login_account = Authentication::login(strval($_POST['login_id'] ?? ''), strval($_POST['password'] ?? ''));
if (null === $login_account) {
    // ログイン失敗
    echo 'NG';
    exit;
}
// XXX 以下、認可処理に続く

Discussion