質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

PHPのパスワード認証について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 527

ysk1118

score 12

ユーザ認証が必要なwebシステムを開発しています。
管理者ユーザはphpよりシステムにログインし、システムを利用するための
ユーザアカウントを作成しています。
作成時にパスワードを設定(通常の文字列)、DB登録時にpassword_hash関数を用いたハッシュ値を
パスワードとして登録、ユーザ認証画面でPassword_verify()にて認証を行う、という仕組みです。

 発生している問題・エラーメッセージ

・ユーザ新規登録用のPHPで登録されたユーザ・パスワードでは、ログイン認証処理において
パスワード認証(password_verify())でNGとなってしまいます。(ユーザIDあるいはパスワードに誤りがあります。と表示)
・管理者権限を持ったユーザが別途用意してあり、管理者ユーザでwebシステムにログインすれば
パスワード変更画面から他のユーザ情報(パスワード)を変更できますが、
この画面でパスワードを変更してやると、正常に認証されるようになります。
(新規登録時と同じ文字列を指定しても認証OKとなる。)
・パスワードは、password_hash関数で与えた文字列から取得したパスワードのハッシュ値を
データベースに登録するようにしています。ソースを比較してみても、新規登録と変更で
特に違いがあるようには思えません

上記のことから、新規登録画面と変更画面で何か処理を誤っているのかと思いましたが、
ソースを比較した限りでは、どちらもPassword_hashによって取得したハッシュ値をDBに登録してあり、
どうして新規登録直後はNGとなり、同じパスワードでも変更処理でOKになるのかがわかりません。
下記ソースに何か原因と考えられるミス等があればご教示いただけませんか。
よろしくお願いいたします。

 該当のソースコード

1)ユーザ新規登録処理

     // 入力したユーザID、パスワードを格納
        $userid = $_POST["userid"];
        $username = $_POST["username"];
        $password = $_POST["password"];
        $scode = explode(" ",$_POST["sCode"]);

        //useridの登録済み確認 '18.11.29 upd -- SQLインジェクション脆弱性対処
        //$sql="select * from t_userdata where userid=" . $userid;
        //$rows=$pdo->query($sql);
        $res=$pdo->prepare("select * from t_userdata where userid=:userid");
        $res->bindValue(':userid',$userid);
        $res->execute();

        //if($rows->rowCount() > 0){
        if($res->rowCount()> 0){
            $errorMessage=sprintf("ユーザーID:%sは既に登録されています。",$userid);
        }else{
            // エラー処理
            try {
                $stmt = $pdo->prepare('INSERT INTO t_userdata(userid, name, password, scode) VALUES (:userid, :name, :passwd, :scode)');
                $stmt->bindValue(':userid',$userid);
                $stmt->bindValue(':name',$username);
                $stmt->bindValue(':passwd',password_hash($passwd,PASSWORD_DEFAULT));
                $stmt->bindValue(':scode',$scode[0]);

                $stmt->execute();

                $signUpMessage = '登録が完了しました。登録IDは '. $userid. ' です。パスワードは '. $password. ' です。';  // ログイン時に使用するIDとパスワード

                $userid="";
                $username="";
                $password="";
                $scode="";

            } catch (PDOException $e) {
                $errorMessage=$e->getMessage();
            }

            $stmt=null;
        }

2)ユーザパスワード変更処理

   // 入力したユーザID、パスワードを格納
   $userid = $_GET["SNO"];
   $password = $_POST["password"];
   $scode = $_POST["section"];

   // 3. エラー処理
   try {
        $stmt = $pdo->prepare("update t_userdata set password=:passwd,sCode=:sCode,passwd_change=:passwd_change,term=:term where userid=:userid");
        $stmt->bindValue(':passwd',password_hash($password, PASSWORD_DEFAULT));// パスワードのハッシュ化を行う
        $stmt->bindParam(':sCode',$scode);
        $stmt->bindParam(':userid',$userid);
        $stmt->bindValue(':passwd_change',null,PDO::PARAM_NULL);
        $stmt->bindParam(':term',$_SESSION["term"]);

        $stmt->execute();

        $good_msg = 'Update Successful!';  // ログイン時に使用するIDとパスワード
   } catch (PDOException $e) {
        $errorMessage = $e->getMessage();
   }

3)ユーザ認証処理

       //入力されたユーザIDを格納
            $userid=$_POST["userid"];

            // 2.ユーザIDとパスワードが入力されていたら認証する
            $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8',$db['host'],$db['dbname']);

            // 3.エエラー処理
            try {
                $pdo=new PDO($dsn,$db['user'],$db['pass'],array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

                $stmt=$pdo->prepare('select * from t_userdata where userid=?');
                $stmt->execute(array($userid));

                $password=$_POST["password"];

                if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                    if (password_verify($password,$row['password'])){
                        session_regenerate_id(true);

                        // 入力したIDのユーザ名取得
                        $id=$row['id'];
                        $res=$pdo->prepare("select * from t_userdata where id=:id");
                        $res->bindValue(":id",$id);
                        $res->execute();
                        $user=$res->fetch(PDO::FETCH_ASSOC);

                        $_SESSION["NAME"]=$user['name'];            //氏名取得

                        $res=null;

                        header("Location: main.php");    // メイン画面へ遷移
                        exit();        // 処理終了
                    }else{
                        // 認証失敗
                        $err_msg='ユーザIDあるいはパスワードに誤りがあります。';
                    }
                }else{
                    // 該当データなし
                    $err_msg='該当データ無し';
                }
            }catch (PDOException $e){
                $err_msg='データベースエラー';
            }

 補足情報(FW/ツールのバージョンなど)

PHP 7.1.6
MariaDB 10.1.24

ユーザ情報格納テーブルの構造
イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • otn

    2018/11/29 14:35

    SQLインジェクション脆弱性がありますね。

    キャンセル

  • ysk1118

    2018/11/29 15:11

    ご助言ありがとうございます。よろしければ、どの部分が該当箇所か、ご教示いただけませんか。

    キャンセル

  • otn

    2018/11/29 15:21

    //useridの登録済み確認 の部分

    キャンセル

  • ysk1118

    2018/11/29 15:42

    ありがとうございます。ソースの該当箇所を修正しました。

    キャンセル

回答 1

checkベストアンサー

+3

$password = $_POST["password"];
$stmt->bindValue(':passwd',password_hash($passwd,PASSWORD_DEFAULT));

おそらく、変数名の間違いが原因です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/29 14:26

    passwdとpasswordが混在して混乱してるだけなのだから、整理すればいいのに。

    キャンセル

  • 2018/11/29 14:55

    ご指摘、ありがとうございました。
    何度も見直したつもりでしたが、全く気づきませんでした。
    本当にお恥ずかしい限りです。

    m6u様の助言にも従い、変数名等整理をしたいと思います。
    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る