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

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

新規登録して質問してみよう
ただいま回答率
85.51%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

14497閲覧

ハッシュ化したパスワードが一致しない

aaaaaaaa

総合スコア501

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

2クリップ

投稿2015/12/07 11:44

下記のソースにて前頁から送られてきたパスワードとDBに存在する既にハッシュ化されたパスワードを照合しています。

しかし、前頁から、ハッシュ化されたパスワードに対応する値を下記のソースに送信しているのにも関わらず照合が一致せず次の処理に進まないのです。
もちろんですが、DBに存在するパスワードをハッシュ化しなければ、前頁で記述したパスワードは一致します。なぜハッシュ化した途端上手くいかなくなるのでしょうか。

php

1<?php 2try { 3 require_once '../lib/dbaccess.php'; 4 require_once '../common/common.php'; 5 6 $post = sanitize($_POST); 7 $member_email = $post['email']; 8 $member_pass = $post['pass']; 9 10 $dbh = dbaccess(); 11 $sql = 'SELECT code,password,name,email FROM dat_member WHERE email=?'; 12 $stmt = $dbh->prepare($sql); 13 $data[] = $member_email; 14 $stmt->execute($data); 15 16 $rec = $stmt->fetch(PDO::FETCH_ASSOC); 17 $db_pass = $rec['password']; 18 if(!password_verify($member_pass, $db_pass)) { 19 echo <<<EOL 20 <p>パスワードが間違っています。</p> 21 <a href="./member_login.html">戻る</a> 22 EOL; 23 } else { 24 session_start(); 25 $_SESSION['member_login'] = 1; 26 $_SESSION['member_code'] = $rec['code']; 27 $_SESSION['member_name'] = $rec['name']; 28 header('Location: ./shop_list.php'); 29 } 30 $dbh = null; 31 32 $rec = $stmt->fetch(PDO::FETCH_ASSOC); 33 } catch(Exception $e) { 34 echo <<<EOL 35ただいま障害により大変ご迷惑をおかけしております。 36EOL; 37 exit(); 38 } 39 ?>

@common.php

php

1 <?php 2 function sanitize($before) { 3 foreach($before as $key => $value) { 4 $after[$key] = htmlspecialchars($value); 5 } 6 return $after; 7 };

@前頁

html

1<!DOCTYPE html> 2 <html lang="ja"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=divise-width, initial-scale=1, user-scalable=1"> 6 </head> 7 <body> 8 <h1>会員ログイン</h1> 9 <form method="post" action="./member_login_check.php"> 10 <label><p>登録メールアドレス</p><input type="text" name="email"></label> 11 <label><p>パスワード</p><input type="password" name="pass"></label> 12 <input type="submit" value="送信"> 13 </form> 14 </body> 15 </html>

@パスワードをハッシュ化しDBに保存するときのソース

php

1<中略> 2if($chumon == 'chumontouroku') { 3 $sql = 'insert into dat_member (password,name,email,postal1,postal2,address,tel,danjo,born) values(?,?,?,?,?,?,?,?,?)'; 4 $stmt = $dbh->prepare($sql); 5 $data = array(); 6 7 function password($password) { 8 $options = array('cost' => 10); 9 return $reg_pass = password_hash($password, PASSWORD_DEFAULT, $options); 10 } 11 12 $reg_pass = password($reg_pass); 13 $data[] = $reg_pass; 14 $data[] = $onamae; 15 $data[] = $email; 16 $data[] = $postal1; 17 $data[] = $postal2; 18 $data[] = $address; 19 $data[] = $tel; 20 if($danjo == 'dan') { 21 $data[] = 1; 22 } else { 23 $data[] = 2; 24 } 25 $data[] = $birth; 26 $stmt->execute($data); 27 <中略>

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12153369172

ikuwow👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kurosawa

2015/12/07 12:51

動作させるPHPのバージョンはいくつでしょうか?
guest

回答3

0

ベストアンサー

いろいろな原因が考えられると思いますが、DBのカラム幅はどうなっていますか?
下記リファレンスによれば、余裕を持ったカラム幅に設定しておくことが推奨されています。
password_hash — パスワードハッシュを作る

結果をデータベースに格納するときにはカラム幅を 60 文字以上にできるようなカラムを使うことをお勧めします (255 文字くらいが適切でしょう)。

もし、DBのカラム幅が不足していると、DBがに格納した時点で尻切れになってしまう危険があります。

一方、DBのカラム幅が広すぎると、DBからパスワードを取り出した際に、末尾に余分な空白が付加されてしまっている場合もあります。

ですので、下記の関数で具体的にどのようにパスワードの比較をしているのか分かりませんが、

PHP

1password_verify($member_pass, $db_pass)

の部分の引数 $member_pass$db_pass の中に、実際にどんな値が入っているか?(末尾の空白も含めて)を直に確認してみるのが確実だと思います。

投稿2015/12/07 13:26

pi-chan

総合スコア5936

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aaaaaaaa

2015/12/08 05:34

ご回答有難うございます。 ご指摘の通り尻切れトンボになっておりました。無事解決しました。
guest

0

password_verify が使われていましたね。失礼しました、下記は問題ありません。。


password_hashのソルトは毎回ランダムなものが利用されます。ゆえにDBにある、事前に生成した「ハッシュ済みパスワード文字列」と、パスワード入力されて照合する際に生成されるハッシュ文字列とは、異なった内容になると思います。


あと、余談ですみませんが、初っ端でPOST変数のsanitize(htmlspecialchars)を行っている箇所は、ちょっと怪しいです。

htmlspecialcharsは、HTML出力するために利用するもので、使うところはヒアドキュメントの中や直近です。

Qiita - $_GET, $_POSTなどを受け取る際の処理

もしパスワード文字列内に & < > などがあれば、ここで加工されてしまいますので、ハッシュ関係の処理でうまく行えたとしても照合結果NGとなるでしょう。

POSTやGETされる値の安全な取得は、filter_input 関数を利用すると便利です。

投稿2015/12/08 05:20

編集2015/12/08 05:44
hsk

総合スコア728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aaaaaaaa

2015/12/08 06:40

ご回答有難うございます。 sanitize関連を読ませていただきました。取得した値を表示する直前に、ということですね。表示するというのは、html上にということなのでしょうか。
hsk

2015/12/08 08:04 編集

>表示するというのは、html上にということなのでしょうか。 仰る通りです。ブラウザに対して < や > などHTMLタグとして認識してほしくない場合などに、&lt; &gt; などへ置き換える(HTMLエンコードする)関数がhtmlspecialcharsです。 たとえば「メモ帳」や「掲示板」的なアプリを作ったとして、もしHTMLエンコードをしないと "KYOTO<NAGOYA>SHIN-YOKOHAMA" とメモ入力した場合、ブラウザは<NAGOYA>の箇所をHTMLタグと認識して "KYOTOSHIN-YOKOHAMA" と表示してしまいます。表示されないどころか、意図的に <script>location.href='危険なサイトのURL';</script> と入力されたりして、セキュリティ上問題を起こしてしまいます。 かといって、受信した文字データを最初から加工してしまうと、< や > などをそのままデータとして意味を持たせたい(使いたい)場合に困ってしまいます。ご質問のパスワード照合で、パスワード文字にアンパサンドも許容している場合、& が &amp;に変換されてしまいますので、(ハッシュ処理は省略します) m#&83R といったパスワードを指定したとき m#&amp;83R と比較をすることになってしまいます。 ちなみに、データベースを利用する場合のSQL文に関するサニタイズも、上記のような理由から、SQL文を生成する直前に文字列データをサニタイズするか、バインド機構を利用します。
guest

0

パスワードの暗号化で、引数に PASSWORD_DEFAULT を利用しており、
さらに option に salt 指定されてたので、 bcrypt アルゴリズムを期待してるのかなぁと思いました。

$options = array('cost' => 10); return $reg_pass = password_hash($password, PASSWORD_DEFAULT, $options);

ただ、、
これは PHP 5.5.0 ならば、bcrypt アルゴリズムが採用されるだけであり、バージョンによってアルゴリズムが変わる(optionも変わるし、尻切れもありうる)ので、まずはバージョンを伺った次第です。

まずは解決したとのことなので、なによりです。

投稿2015/12/08 12:43

kurosawa

総合スコア780

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問