他のサイトでもEC-CUBEのID&パスワードを使えるようにする。
あまり需要はないかもしれませんが、EC-CUBEの関連サイトなんかを作った時には便利かもしれません。
やり方は至って単純で、EC-CUBEが使っているMySQLを外部のPHPから叩いているだけです。
ただ、会員情報が入っているdtb_customerテーブルのpasswordは平文ではなくSHA256でハッシュ化されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * パスワードのハッシュ化 * * @param string $str 暗号化したい文言 * @param string $salt salt * @return string ハッシュ暗号化された文字列 */ function sfGetHashString($str, $salt) { $res = ''; if ($salt == '') { $salt = AUTH_MAGIC; } if (AUTH_TYPE == 'PLAIN') { $res = $str; } else { $res = hash_hmac(PASSWORD_HASH_ALGOS, $str . ':' . AUTH_MAGIC, $salt); } return $res; } |
単純にパスワード文字列をsha256でハッシュ化すると、レインボーテーブル(ありがちな単語を予めハッシュ化したテーブル)に弱くなるので、パスワード+乱数などを組み合わせてからハッシュ化します。この時の乱数をソルトといいます。
EC-CUBEでは、以下の2つのソルトを使っているようです。
1つ目は、AUTH_MAGICは、EC-CUBEインストール時に生成される小文字アルファベット乱数(data/config/config.php)
2つ目は、文字通りのsaltは、会員登録時に生成される10ケタの小文字アルファベット乱数(cutomerテーブルのsaltフィールド)
なので、以下の手順でログインを行う
AUTH_MAGICは予め取得しておく
ログインIDであるメールアドレスをキーにレコードを取得
取得したsaltフィールド、AUTH_MAGIC、入力されたパスワードを使って、hash_hmac関数でハッシュ化。
DBから取得したハッシュ化パスワードと同じなら認証成功!
以下、サンプルソースです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
<?php define('AUTH_MAGIC', 'haiwoclalouwregukepaejodicleadeceanaelec'); define('PASSWORD_HASH_ALGOS', 'sha256'); //トークンをパスしたら、新しいセッションID(トークン)を発行する //Chromeではブラウザを閉じても更新されないので、明示的に更新する。 session_regenerate_id(TRUE); // カレントの言語を日本語に設定する mb_language("ja"); // 内部文字エンコードを設定する mb_internal_encoding("UTF-8"); //DB接続情報を読み込む require_once "./conf/dsn.php"; //データベースに接続 try { $pdo = new PDO('mysql:dbname='. $dsn['dbname'] .";host=" . $dsn['host'], $dsn['user'], $dsn['pass']); } catch (PDOException $e) { exit('Can not Connect DB!' . $e->getMessage()); } //静的プレースホルダを指定(デフォルトは動的) $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,FALSE); $stmt = $pdo->query('SET NAMES utf8'); if (!$stmt) { $info = $pdo->errorInfo(); exit($info[2]); } //POSTから変数に格納 $login_id = isset($_POST["login_id"]) ? $_POST["login_id"] : ""; $login_pass = isset($_POST["login_pass"]) ? $_POST["login_pass"] : ""; //一応、サニタイズ $login_id = htmlentities($login_id); $login_pass = htmlentities($login_pass); //DBからレコード取得(passwordは予約語なので、バッククォートで囲まないと取得できない!) $sql = 'select name01,name02,salt,`password` from dtb_customer where email = ?'; $stmt = $pdo->prepare($sql); $flag = $stmt->execute(array($login_id)); if (!$flag) { $info = $stmt->errorInfo(); exit($info[2]); } //取得したレコードを変数に格納 $name01 = ""; $name02 = ""; $salt = ""; $db_hash_pass = ""; while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { $name01 = $data['name01']; $name02 = $data['name02']; $salt = $data['salt']; $db_hash_pass = $data['password']; } // エラーメッセージ $errorMessage = ""; // 画面に表示するため特殊文字をエスケープする // $viewUserId = htmlspecialchars($_POST["userid"], ENT_QUOTES); // ログインボタンが押された場合 if (isset($_POST["login"])) { // フォームから受け取ったパスワードをソルト付でハッシュ化する $input_hash_pass = hash_hmac(PASSWORD_HASH_ALGOS, $login_pass . ':' . AUTH_MAGIC, $salt); // 認証成功 if ($db_hash_pass === $input_hash_pass) { echo "login OK!"; } else { $errorMessage = "ユーザIDあるいはパスワードに誤りがあります。"; } } ?> <!doctype html> <html> <head> <meta charset="UTF-8"> <title>サンプルアプリケーション</title> </head> <body> <form id="loginForm" name="loginForm" action="<?php print($_SERVER['PHP_SELF']) ?>" method="POST"> <fieldset> <legend>ログインフォーム</legend> <div><?php echo $errorMessage ?></div> <label for="userid">ユーザID</label><input type="text" id="login_id" name="login_id" value=""> <br> <label for="password">パスワード</label><input type="password" id="login_pass" name="login_pass" value=""> <br> <label></label><input type="submit" id="login" name="login" value="ログイン"> </fieldset> </form> </body> </html> |