🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
PHP

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

Q&A

6回答

1605閲覧

password_verifyで認証されない

Res

総合スコア184

PHP

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

0グッド

2クリップ

投稿2019/11/12 10:06

編集2021/04/21 13:06

実現したいこと/ソースコード

ログインの認証時に、password_verifyで認証をしているのですが、認証されません。
また、別のテストページで少しスクリプトが違うハッシュ化と確認を試したところ正常にtrueが返されました。
コードは次のようになっています。

signup.php

php

1//~~~省略~~~ 2$emails = ""; 3$userids = ""; 4try { 5 $pdo = new PDO('mysql:host=example.jp;dbname=user_data;charset=utf8','user','password',, 6 array(PDO::ATTR_EMULATE_PREPARES => false)); 7}catch(PDOException $e){ 8 exit("spl"); 9} 10$stmt = $pdo->query("SELECT * FROM user_tb"); 11while($row = $stmt -> fetch(PDO::FETCH_ASSOC)) { 12 $emails .= "[". $row["email"] ."]"; 13 $userids .= "[". $row["userid"] ."]"; 14} 15function ra(){ 16 $len=""; 17 for( $i = 0; $i < 10; $i++ ){ 18  $len.=substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 10); 19 } 20 return $len; 21} 22 function newusers( $userids ) { 23 $kuserid=ra(); 24 if(strpos( $userids , $kuserid ) !== false){ 25 newusers(); 26 } else { 27 try { 28 $pdo = new PDO( 'mysql:host=example.jp;dbname=user_data;charset=utf8' , 'user' , 'password', 29 array(PDO::ATTR_EMULATE_PREPARES => false)); 30 } catch ( PDOException $e ){ 31 exit( "sql" ); 32 } 33 $name = $_POST['name']; 34 $email = $_POST['email']; 35 $pass1 = $_POST['password']; 36 $pass2 = $_POST['password2']; 37 $niti=date( "Y/m/d H:i:s" ); 38 $stmt = $pdo->prepare("INSERT INTO user_tb (name, password,password2,userid,createddate,email) VALUES (:name, :password,:password2,:userid,:createddate,:email)"); 39 $pass1s=password_hash($pass1, PASSWORD_DEFAULT);//ここでハッシュ化 40 $pass2s=password_hash($pass2, PASSWORD_DEFAULT);//ここでハッシュ化 41 $stmt->bindParam(':name', $name, PDO::PARAM_STR); 42 $stmt->bindParam(':password', $pass1s, PDO::PARAM_STR); 43 $stmt->bindParam(':password2', $pass2s, PDO::PARAM_STR); 44 $stmt->bindParam(':email', $email, PDO::PARAM_STR); 45 $stmt->bindParam(':userid', $kuserid, PDO::PARAM_STR); 46 $stmt->bindParam(':createddate', $niti, PDO::PARAM_STR); 47 $stmt->execute(); 48 $_SESSION['id'] = $kuserid; 49 exit("ok"); 50 } 51 } 52function fu001 ( $emails ) { 53 $email = $_POST['email']; 54 if(strpos( $emails , $email ) !== false){ 55 exit( "emailerror" ); 56 }else { 57 newusers( $userids ); 58 } 59} 60fu001( $emails ); 61//~~~省略~~~

login.php

php

1try{ 2 $emails = array(); 3 $passs = array(); 4 $userids = array(); 5 $ivs = array(); 6 $pdo = new PDO( 'mysql:host=example.jp;dbname=user_data;charset=utf8' , 'user' , 'password' , 7array(PDO::ATTR_EMULATE_PREPARES=>false)); 8}catch( PDOException $e ) { 9 exit('sql'); 10} 11$stmt = $pdo->query("SELECT * FROM user_tb"); 12while($row = $stmt -> fetch(PDO::FETCH_ASSOC)){ 13$emails[] = $row["email"]; 14$passs[] = $row["password"]; 15$userids[] = $row["userid"];} 16$email = $_POST['mail']; 17if( in_array( $email, $emails ) ){}else{ exit("error"); }//メールアドレスが存在するかどうか 18$pass = $_POST['pass']; 19$mi = count($emails); 20for( $i = 0; $i < $mi; $i++ ){ 21 if( $emails[$i] === $email ){ 22 if( password_verify( $pass , $passs[$i]) ) {//ここで確認 23 $_SESSION['id'] = $userids[$i]; 24 exit("login"); 25 }else{ 26 exit("pass"); 27 } 28 } 29}

※質問に関係ない部分は一部省略しているほか、一部実際と異なりますが質問のコードとは無関係です。
何回アカウントを作り直してもfalseになってしまいます。

追記1

回答者からいただいたソースコードでlogin.phpのコードを改めました。

php

1try { 2 $pdo = new PDO('mysql:host=example.jp;dbname=user_data;charset=utf8','user','password', 3 array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION) 4 ); 5 $stmt = $pdo->prepare('SELECT userid, email, password FROM user_tb WHERE email = :email'); 6 $stmt->bindValue(':email', $_POST['mail']); 7 $stmt->execute(); 8 $result = $stmt->fetchAll(); 9 if ($result === false) { 10 exit('fetch error'); 11 } 12 if ($resul ===array()){ 13 exit('pass'); 14 } 15 //exit($_POST['pass'].":". $result[0]['password']); 16 if (password_verify($_POST['pass'], $result[0]['password'])) { 17 $_SESSION['id'] = $result[0]['userid']; 18 exit('login'); 19 } 20 else { 21 exit('pass'); 22 } 23} catch (PDOException $e) { 24 exit('sql:' . $e->message); 25}

情報

皆様、貴重なお時間を頂きこの質問に回答してくださり、誠にありがとうございました。
今回解決することはできませんでしたが、質問の仕方に対する指摘等を、大切なお時間を割いて回答していただき非常に感謝しております。
お忙しい中ありがとうございました。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/11/12 11:03

forループの中でglobal宣言せず、予めforループの外で普通に変数を宣言しておけばいいんじゃないかな。
Res

2019/11/12 11:21 編集

それってloginのverifyですか?
m.ts10806

2019/11/12 11:35

コード全体がないのとインデント全くないので見通せません。手元のコードから調整してコードもなるべく全体の流れがわかるコードで提示願います
m.ts10806

2019/11/12 11:35

globalを使った意図も説明願います
Res

2019/11/12 11:49

globalは前の時のコードの消し忘れです。あってもなくてもいいので残ってます。
m.ts10806

2019/11/12 12:32

インデントはできませんか? 難しければWeb上のコード整形サービスかコードフォーマット機能のあるエディタを利用してください。 読みづらいコードは問題切り分けを困難にします。(残っているglobalも同じく。なくて差し支えないなら早い段階で消すべき。)
Res

2019/11/12 12:52

すぐやります。
Res

2019/11/12 12:59

いつもインデントを消してしまう癖があるので.....
m.ts10806

2019/11/12 13:50

https://okuden-labo.com/home/php-code できればEclipseなどコードフォーマット機能のあるエディタを使ってほしいです。 可読性の良し悪しはコードの品質にも直結します(それが趣味や学生であっても。回答者は読む気をなくす人が多いです)
退会済みユーザー

退会済みユーザー

2019/11/13 00:34

質問者さんの思う「無関係」は第三者が検証してはじめて「無関係」と言えるものです。動かしているコードと違うコードを示されても、そこが問題なければ、示されていない箇所に問題があるとしか思えないので、より実態に近いものを示したほうが解決が近くなります。
m.ts10806

2019/11/13 13:49 編集

改善してほしいところを書いてと言われましても、せっかくの回答者のコードを改悪して「できない」と言っている状況では書いてもらえる可能背は低く、ヘイトを集めるだけです。 厳密に言えば下記も質問要件とは関係ありません。あなたの個人的な想いです。 「11/13/21:37: やってほしいことだけを記載した丸投げの質問と思うならば、なぜそうおもったのか。改善してほしいところを教えてください。 」
退会済みユーザー

退会済みユーザー

2019/11/14 00:48 編集

質問者さんの抱えている状況を第三者が再現して検証できる状況にならない限り、単なる丸投げ、無償デバッグ依頼にしかなりません。回答者に掛かる負担のことまで気持ちを配って、問題解決してもらおうと工夫することはできませんか? 現時点で質問者さんのコードと回答者のコードが別(無関係と言って省略している)であったり、データベースを利用しているのにデータベースに関する情報(mysqlとかpostgresqlとか、それらのバージョンとか、テーブル構造CREATE TABLE文とか、サンプルデータとか)が出てこない「いびつさ」も気になります。問題点を絞り込むために、質問者さんも回答側も同じデータベースを再現し、同じphpコードを動かし、検証して見る必要があります。解決につながる動きが必要なのは質問者さんなのに、全く動く気配がない。解決させようという気がないと思われてもしかたないのではないでしょうか。「無関係」と言い張っている以上、進展しませんよ。情報がない中で適当に動く(かもしれない)コードを回答者が示したところで不満なんでしょ?
Res

2019/11/14 12:24

ありがとうございます。言われたと通り情報を追記しました。
Res

2019/11/14 12:24

あまり質問にも慣れていないもので。
m.ts10806

2019/11/14 21:16 編集

「問題」は質問者が認識している範囲だけとは限らないというのは分かりますか? その部分の指摘を「無関係」と切り捨てるおつもりなら得られるアドバイスはありませんし、今の問題すら解決はしません。 あとちょこちょこ言い訳を挟んでこられるのでアドバイスが受け入れられるか疑問で、余計にアドバイスを得られる機会を失しています。 回答者はあなたより沢山の経験をしているし技術も知見も持っています。 既に指摘されているかもしれませんが、「関係ない」と判断できるだけの経験も知見もお持ちなのですか?でしたらなぜ質問したのですか? 繰り返すようですが、「自分が思ってることだけ解決すればいい」という自己中心的な考え方だと誰も手をさしのべません。 解決する気がないと見ている人は認識します。(View数が多いのはどこかに悪い質問例ということで晒されてるんでしょうね)
kyoya0819

2019/11/14 23:49

> View数が多いのはどこかに悪い質問例ということで晒されてるんでしょうね 自分の知る範囲だと数か所に貼られてそれが拡散されている感じですね
date

2019/11/15 00:08

テーブル構造を見せてほしいというのはもしかしたらpasswordカラムとかがINT(11)とかVARCHAR(12)とかになってて、passwordにデータがちゃんと入っていないかもしれない。 とかがあるから聞いています
Res

2019/11/15 06:45

100%無関係と断定できます。
Res

2019/11/15 06:55

その部分を載せるとセキュリティ上よくないからです。 全て載せれるというわけには申し訳ありませんがいけません。
m.ts10806

2019/11/15 07:03

>100%無関係と断定できます。 どこがでしょうか。根拠がわかりません。 現にm6uさんのアドバイスを突っぱねています。私は無関係には思えません。コードの見やすさ、デバッグのしやすさはプログラミングする上では全て関係してきます。品質はもちろん、その人の頭がきちんと整理できているかとか、様々なことが見えてきます。 それを無関係となぜ言えますか? 「コード読む気にならん」という意見もあるなかでなぜ無関係と言い切れますか? コード読んでもらえないのになぜ解決できると言い切れますか?
Res

2019/11/15 07:05

>その部分を載せるとセキュリティ上よくないからです。 といったように申し訳ありませんが「絶対」追記できません。
m.ts10806

2019/11/15 07:17

データならともかくテーブル定義で問題になることってそうそうないと思いますね。 もしセキュリティリスクを考慮するなら求められているカラムだけでもいいし、そもそもこのような危ない実装をしているというのを全世界に発信しているというほうがリスク高いです。
退会済みユーザー

退会済みユーザー

2019/11/15 07:20 編集

明かせないリアル情報なんて要りません。 teratail上で必要なことは、質問者と回答者側との間に、 テストや検証用にミニマルなphpコードと、テーブルのテスト用データがあればいいのです。 それで動いたという礎(証左)を元に、本番データに近いものでテストするのです。 (付き合ってやりたいが、こっちも本業があるものでな。)
Res

2019/11/15 07:59 編集

>現にm6uさんのアドバイスを突っぱねています。 >質問者さんの抱えている状況を第三者が再現して検証できる状況にならない限り 再現して検証できるよう、できる限りの情報を記載しました。 私のサイトはHTMLのみでバックグラウンドが見えるような素っ裸にしていいサイトではないです。 ※「HTMLのみ」は見た目やコードの問題ではなくphpのようにユーザーに見えるかどうかをあらわしただけです。 もちろん回答者さんの「このままで解決できない」を私なりに今まで追記しました。 私は質問者なので回答者じゃありませんし、回答者の思うことは回答者に聞くしかありません。 今まで回答者を考えてください。とアドバイスをいただきましたが、質問者の立場も少しは考えてくださるとありがたいです。私自身質問にすべてのソースコードを漏らしたくないのでいっています。 私は回答者の意見を積極的に取り入れ質問を改善したつもりです。私なりに改善しました。 上から目線で申し訳ありません。
Res

2019/11/15 07:33 編集

>実装をしているというのを全世界に発信しているというほうがリスク高いです。 それはいえてます。今はテスト段階なので構わないです。 この「VIEW 530」の中に不審者がいなければいいですけど...
m.ts10806

2019/11/15 07:39

>私のサイトはHTMLのみのような素っ裸にしていいサイトではないです。 ならphpのコードすら出すべきではないですね。攻撃してくれって言ってるようなもんです。 それに本当に現在のような実装なら「私のサイトは~」と高らかと歌い上げて良い素晴らしい作りにはなってないと思いますが。 HTMLのみのサイトでも素晴らしい作りにはできますし、あまり不特定多数をディスるような発言はされない方が良いかと。 既に加熱しているヘイトに爆弾を追加するだけです。 >この「VIEW 530」の中に不審者がいなければいいですけど... なら、運営に依頼して削除してもらうべきですね。 ログインしてなくても見れるので世界中からアクセス可能です。 私は詳しくないですがview数増やさないように閲覧できる手段もあるんじゃないですかね。
Res

2019/11/15 07:44

はい... >それに本当に現在のような実装なら「私のサイトは~」と高らかと歌い上げて良い素晴らしい作りにはなってないと思いますが。 今はテスト段階なので構わないです。 teratailの運営のようにいろいろと詳しくありがとうございます。 >私は詳しくないですがview数増やさないように閲覧できる手段もあるんじゃないですかね。 確かにそうですね。思ってもいませんでした。
Res

2019/11/15 07:51

>ならphpのコードすら出すべきではないですね。攻撃してくれって言ってるようなもんです。 今回はしょうがないです。 >設計も含めて全部書き直さなきゃどうにもならないレベル 正解です。でも全部は無理なのでまた書き直して、詰まってしまったところでまた質問を出そうと思います。
m.ts10806

2019/11/15 07:57

>正解です わざとやってますか?正解と思うならそんなコードそもそも出さないでください。 ヘイトを集めたいだけなら今後は誰からもアドバイスを得られないと思ってください。 >今はテスト段階なので構わないです。 では出してはいけない項目などそうそうないでしょう。
Res

2019/11/15 08:02

>では出してはいけない項目などそうそうないでしょう。 テスト段階でもじき公開します >わざとやってますか? 正解とはm.ts10806さんが「設計も含めて全部書き直さなきゃどうにもならないレベル」と言ったことに確信したということ。以上です。
Res

2019/11/15 08:02

あまり聞きださないでください。
date

2019/11/15 08:04

login.phpであるとしたらもしかしたら、input nameはname="pass"じゃないかもしれないとかあるかもしれないので、ログインのhtmlはみせていいのでは、見せないのなら私はここまでです 後一応ですが、今のプログラムだと同じemailがあったら一番初めに登録したemailとパスワードを参照している。テーブル内に同じemailがもしあったら、その時に登録したパスワードじゃないと認証しません 同じemailがあるかどうかみてみてはどうですか
m.ts10806

2019/11/15 08:14

そうですか。では、なにも聞きません。お一人で悩んでください。 質問は削除依頼を運営に出しておいてくださいね。 もうじき公開するものを「テスト」とは表現しませんし、「こんなコード書いてて公開します!」と世界に向けて発信しているわけですから。 ブラウザから確認できない情報を1文字ですら出すべきではないでしょう。 (それにハッキリ言うと今の質問者さんの姿勢を貫く限り1年後に設計含めて劇的に改善されているとは思えない)
Res

2019/11/15 08:23

まだPHP初めて数か月です、、まだまだ勉強して公開したいと思います。 あとじきの表現はまだ先を指しているつもりです。
Res

2019/11/15 08:24

>もうじき公開するものを「テスト」とは表現しませんし はい。テストからそのまま改良していくつもりで、今は「テスト」の段階ということです。 説明不足で申し訳ないです。
m.ts10806

2019/11/15 08:37 編集

公開するのは一旦頭から外して基礎とセキュリティを叩き込んでください。 あと質問の仕方、回答者とのコミュニケーションの取り方も改善してください。 どう見ても回答者からアドバイスを引き出せるようなやり方をしていません。ヘイトを集めてばかりです。 プログラミング初心者ならまだしもコミュニケーション初心者では話になりません(プログラミング経験はほぼ関係ない)。 初めて数ヵ月で何の根拠や自信があって言い切ってるのか知りませんが、出して問題がある情報がそんなにあるものではないですよ? 業務で使っていて顧客情報預かってるとかそういうことかと思ったら初めて数ヵ月が作るログイン認証ですか。 出しちゃいけないのはサーバーIPとかドメインとかDB接続情報くらいのもんじゃないですか(あとは自身の個人情報)。 誰も名前や住所や電話番号教えろなんて言ってません。 ので、テーブル定義やhtml程度が出せない理由はどこにもないですね。しかもそのなかで1つのカラムだけ。 絶対的な独自のサービスが構想にあったとしてもこの内容でそれが現れるようなものではありません。 このコードだって完全独自に組み上げたものではないでしょう? 変に意固地にならず応じていれば投稿して数時間で解決していてもおかしくない内容です。こじれたことは自身が原因と猛省して臨むくらいじゃないと5年10年経っても公開できるものはできませんよ。
Res

2019/11/15 08:57

>変に意固地にならず 最初回答者が言っていることがあまり理解できず、こんがらがってしまいました。 まだ私自身未成年ですし、まだ学ばなければいけないことも多いと思います。 m.ts10806さんの思っていることをしっかりと理解し今後に役立てていこうとおもいます。 今回の質問でご迷惑をおかけして申し訳ありませんでした。
m.ts10806

2019/11/15 09:04

>未成年ですし 先に指摘したように言い訳して逃げる姿勢が問題を大きくしているだけです。 理解できないなら聞くべきです。質問に初心者アイコンでもつけておけばそれだけでも伝わるし、内容から初心者であることは誰の目にも明らかです。聞き方含めた対応の仕方すら間違えなければ「そんなことも知らないのか?」と責められることもないでしょう。 間違えた結果がこれです。 それに大事なのは、問題を投げ掛けたなら解決するまで対応するのが質問者の責任です。年齢や性別、国や地域、経験も関係ありません。 迷惑かける可能性があるのはteratailユーザーやteratail運営ではなく(そりゃ他人の時間使っていることは配慮すべきだけど)、あなたが公開するサイトを利用するであろう人たちです。
Res

2019/11/15 09:49 編集

はい。しっかりと頭に叩き込んでおきます。最後の最後まで本当にご迷惑をおかけして申し訳ありません。そして、たくさんの指導。ありがとうございます。
m.ts10806

2019/11/15 09:42

(2回目) それに大事なのは、問題を投げ掛けたなら解決するまで対応するのが質問者の責任です。 要約: 解決してないなら引き下がろうとするな。
kyoya0819

2019/11/15 10:35

> まだ私自身未成年ですし、まだ学ばなければいけないことも多いと思います。 いや、俺だって未成年だよ
m.ts10806

2019/11/15 10:51

asuchi0819さん マジすか(ここ最近でトップ3くらい驚いたかもしれない)
kyoya0819

2019/11/15 13:05 編集

m.ts10806さん マジっすね でも未成年でもここまで知識がつけられたのはm.ts10806さんなどのteratailの回答者さん方のおかげです、
m.ts10806

2019/11/15 14:25

asuchi0819さん ここで言うことではないかもしれませんが、そう言ってくれて嬉しいですね。 回答者続けてきた意味があります。
guest

回答6

0

まだ「受付中」らしいので回答してみます。

ただ、私の回答スタンスとして
要件不明瞭な質問にはズバリは応えない。ヒント回答しかしない
というのがあるので、「コピペで動くコードもらえた」「絶対の解決策がもらえた」という期待はしないこと。

もしコメントしたいのであれば
表向きだけの感謝の意は良いので、正しく理解したかどうかを分かるコメントにしてください。
ガイドライン#4-2. どのように解決したのかを伝えましょうにもある通り。)


細かいツッコミをするとキリがない。
ただ、コーディングする上で最低限下記は守るべき

  • インデントは揃える。後からではなく始めから。
  • 開発中ならエラー表示は常にONにしておく
  • デバッグ環境を整える
  • エラーを読む
  • ドキュメント、リファレンス、マニュアルは読む
  • 変数名は意味のある名前を付ける(マジックナンバーはダメ絶対)
  • コード内でまとまりごとに改行を入れる(可読性の問題)
  • 関数とグローバルの処理は明確に場所を分ける(可読性の問題)
  • ロジックと画面表示部分は明確に場所を分ける(可読性の問題)
  • DBを利用する場合、何も使わないデータは保存しない
  • DB関係でtry-catchはDB接続部分だけじゃなくSQL送信から結果を受け取るところまで囲う(DB接続なんて一度確立すればそうそうException起きない)
  • try-catchで捕捉したExceptionはきちんと何かに出力する。(Exceptionを握りつぶすとか得た情報を何も使わないとか以ての外)
  • 同じことを何回も書かない
  • いきなり全部書かない(ミニマムコードから書く)
  • 自分が解説できないコードを書かない

まあ「最低限」と言いましたけど、結構あるんですよね。

初心者ということなので(初心者アイコンついてないしプロフィール見てると「回答します」と書いてあるので驚愕しかないけど)、知らないことも多いかもしれないけど、1個1個確認してみると良いです。
ほぼほぼ守られていないことが分かるはず。

ということで、今回の件は、下記のようなコードから始めるべきなんですよね。

php

1<?php 2ini_set('display_errors', "On"); 3 4$user_pass_on_db = password_hash("test", PASSWORD_DEFAULT); 5 6echo $user_pass_on_db.PHP_EOL;# DBに入る想定のパスワード 7echo mb_strlen($user_pass_on_db).PHP_EOL; 8 9$user_pass_from_form_y = "test"; #入力フォーム 一致 10$user_pass_from_form_n = "test2"; #入力フォーム 不一致 11 12var_dump(password_verify( $user_pass_from_form_y , $user_pass_on_db) ); 13var_dump(password_verify( $user_pass_from_form_n , $user_pass_on_db) ); 14

このコードで確認できてないことはDB介してもフォームからの値を受け取って云々もできるはずがありません。
これがベースになれば、DBに必要な桁数も分かるし、DBに保存された情報との照合も出来るわけです。

コードをざっと読んだ限り、このミニマムコードでの確認すら出来てなさそうなのでここから書いています。
どこも大丈夫なところなんてありません。
安心できるところなんてどこにもありません。

書かれた内容が全てです。書いてないことまで拾うことはどんな熟練者でもできません。
指摘されるということは、それだけ何も伝わっていないということです。
伝わっていないから指摘されるのです。

回答者は今回の質問者よりも多くのコードを読んでいるし、書いています。
「コピペのツギハギだろうな」ということは読めば分かります。
「自身が書いたコードの理解度」もコメントからコードから読み取ることができます。

既についている回答が全てです。
それらを「関係ない」「話をそらしている」と言えるレベルではないことは誰の目にも明らかです。


ということで、私が書いたコードを1つの部品の参考として、
部品を作っていき単体確認を行った上で結合していってください。

DBのデータを保存、それを利用して照合 は本当に最後のほうで良いでしょう。


さて。

テーブル構造を見せてほしいというのはもしかしたらpasswordカラムとかがINT(11)とかVARCHAR(12)とかになってて、passwordにデータがちゃんと入っていないかもしれない。

という依頼に対して

その部分を載せるとセキュリティ上よくないからです。

という返答はどう考えても間違っています。

だって、既にmysqluser_tableというデータベース名のuser_tbという名前のテーブルにname,password,password2,userid,createddate,emailというカラムがあるということまでコードで出ていますよね。
そこまで出しているのに今更password varchar(255) NOT NULLのような1つのカラムの定義を出すことにどんなセキュリティリスクがありますか?
言い切れるなら根拠を示さないと誰も納得しません。しかも「初めて数ヶ月」程度の初心者が「絶対」と言い切れる意味は誰も理解できません。

納得させたいならきちんと技術で証明して納得させてください。
teratailはプログラミング特化のQAサイトです。初心者とか上級者とか関係ありません。
言葉よりも技術力が最も相手を納得させる確実な手段です。口では誰も納得しません。

よく見かける「調べたけど分かりません」という決まり文句に何の説得力もないのと同じです。

それに少し調べればpassword_hash()で PASSWORD_DEFAULT を指定すればどれくらいの文字数を出してくるか分かります。
paiza.ioのように環境作らなくても今回私が提示したコードくらいは試せるのです

こういうの「知らなかった」では済まされないんですよ。
それに世界のクラッカーたちはそういう「知らなかった」を狙ってきます。
「初心者だから容赦してくれ」は通じません。初心者こそ格好の餌食でしょう。

だからこそ、「公開する」ことは頭から外して基礎学習とセキュリティの学習に注力すべきと言う話をしました。

それに、どんな優良記事を読んで理解した気になっていたとしても、
今回提示されたコードをきちんと動くような形にするのは、今の質問者さんでは無理です。
認証関係はコピペやツギハギコードで制御しきれるもんじゃないんですよ。
しかもサービスとして公開するつもりなんですよね?一般利用者が必ず意図した操作をしてくれると思いますか?
確かにブラウザから確認できるのはhtmlだけなので、htmlの拙さだけではセキュリティ対策の強弱までは判断できません。

でも、クラッカーたちはどうしたらセキュリティリスクを抱えるサイトであるかを見つける術を知っています。あなたはどこまで知っていますか?
そういうクラッカーたちから自身のサイトを守れる自信がありますか?利用者を守れる自信がありますか?

何がセキュリティリスクで何がセキュリティリスクではないか分かっていない状態で守れるものってあるんでしょうか。

という私のような回答者が投げかける疑問を全て明快に論拠も含めて返せるようになるまで
「公開する」という目標は忘れてください。


最後に、私が最も引っかかった質問者さんの発言をピックアップします。

私のサイトはHTMLのみでバックグラウンドが見えるような素っ裸にしていいサイトではないです。

笑止千万

これだけでどれだけの指摘を受けるか理解できてませんよね。

理解で来たらようやくスタート地点にたったと認められるんじゃないでしょうか。


色々混じったんですけど「質問するな」「初心者は還れ」と言っているわけではないです。
教えを請うならそれなりのやり方がある。
初心者という自覚があるならとるべき言動がある。

それだけの話です。

既にm6uさんなども言ってくれていますが、内容や表現などは別として反応をしてくれるというのは
動機や理由はそれぞれあったとしても「何かしらの形で手を差し伸べてみようか」と決して軽くはない腰をあげてくれていると思ってください。

teratailは長くやっている回答者が多いです。
それだけ質問者のことを見ています。
「こいつアドバイス受け入れる気がないな」と受け取ったら問答無用で無言低評価だけして放置します。
否、もしかしたら低評価すらしなくなるかもしれない。

そうなると困るのは誰でしょうか。

考えてみてください。
別に回答者は質問者がいなくてもどうとも思いません。
回答者自身がプログラミングの問題を抱えているわけではありませんからね。

投稿2019/11/15 14:24

m.ts10806

総合スコア80875

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

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

0

まず、

PHP

1$password = $_POST['password']; 2$password = $_POST['password2'];

の時点でわけわかめです。
なんで二回も代入するんですか?
それによってpassword2ないんじゃね?

てか、2つ入力させて2つともハッシュとかわけわかめの極み

投稿2019/11/14 23:55

kyoya0819

総合スコア10429

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

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

kyoya0819

2019/11/14 23:56

わっけわっかめー
Res

2019/11/15 07:04

安心してください。 実際記載するとき間違えて//を消してしまいました。 見つけてくださりありがとうございます!
m.ts10806

2019/11/15 07:18 編集

その2つとも登録というのも仕様が意味不明ですしね。 設計も含めて全部書き直さなきゃどうにもならないレベルなので「読む気がしない」という意見は賛同しかない。
kyoya0819

2019/12/21 11:23 編集

内容不適により削除
guest

0

まず、情報不足の段階で、解決につながるかどうか怪しい情報を提供し
混乱させてしまったことについては申し訳ないと思っております。

teratail など第三者に自分の関わるコードを評価してもらい
解決につながるアドバイスを得る場合において、
大事なことは、質問者さんと回答者側とで
同じコード、同じデータでテストし評価することです。
開発中のコードを全部開示しろ、
動かすのに必要なデータ全部開示しろ、ということではなく、
要求された機能を満たすだけの最小限(ミニマル)なコードと、
要求された機能をテストするのに必要な、リアルと関係ない仕様を満たすテストデータが必要で、
解決に至る回答をつけようとしてくれる第三者の手元で試せるよう、
質問者さんが頑張って情報提供しないと始まらないのです。

それを怠ってしまうと、
回答者側が再現できなかった部分を適当に解釈してコードを書き、
実態に則さない状態でテストして「もしかしたらこれで解決するんじゃないだろうか」という状態の
回答が寄せられます。
(私が最初に書いたみたいに)

質問者さんが直接動かしている実行環境のコードやデータを開示できないのは、実によくある話です。
それでも teratail などを利用しようとするなら、
開示できる範囲のミニマルなもの(コード、データ構造、テストデータ)を別途工夫して用意しないといけないのです。
めんどうですか? わずらわしいですか? 手間暇かけなくないですか?
そう思うのであれば、そもそも teratail でデバッグ依頼のようなことを投稿してはいけないのです。
それを丁寧にやってくれる質問者さんが、経験豊富な回答者の情報を上手に引き出し、解決にたどり着いています。

回答しようとする側は、
足りない情報を自分の経験や知識に照らし合わせて補おうとしたり、
ネット上の参考情報がないか調べる時間を使ったりと、
質問者さんが考えるよりも多くの時間を(何人もの人が大なり小なり)費やしています。
本業を抱えている人も多く、業務の合間を縫って手助けしようとしてくれているのに、
情報が足りない、テスト用のデータがない部分を工夫するために余計に手間暇をかけて付き合おうとしています。
質問者さん一人がめんどうでわずらわしいのではないのです。

そして今回は、password_verify()の件以外に、
文法エラーや、データベースアクセスにまつわる作法など、さまざまな
「なぜここはこういう書き方をしているのだろう?」という箇所があり、
実行環境の差異を騙して動かそうとしても、password_verify()の件じゃないところで引っかかり、
回答する側としてはそこに手間暇がかかっています。
そこを解決してからpassword_verify()の件に取り組みたい主旨で私は回答を書きました。
それなのに、
「※質問に関係のないことは情報追加・修正依頼に書かないでください。」などと言われては、
デッドロックですよ。
これでアドバイスしようかなと思っていた潜在的な回答者を追い出してしまっています。
(情報セキュリティ方面の第一人者も戸惑っていましたし。)

質問者と回答者側が同じテーブルにつかないと始まらない、
そのために必要な指摘には柔軟に対応してください。
なにもリアルなものを出してくれとは言っていません。
第三者が検証・テストできる情報がほしいだけです。

以下、リニューアル前の回答:

えーっと、回答につながるかどうかわかりませんが、
整形ツールにかけた上で書き直してみた。
机上デバッグのみで、実際に動作まではさせていない点についてはあしからず。

まず、fetch()をwhileループを回して全部溜め込んでから、
$_POST['email']を照会するのってムダ。
1万件や10万件や100万件のユーザー情報の中から探させるのであれば、
もっとデータベースを活用しなさい。
SELECT文でemailを指定することで、存在すれば1行だけ得られるし、存在しなければ何も返ってこない。
高々1行分のデータを受け取るのだからfetchAll()を使ってみたけど、どうだろうか。

PHPでデータベースに接続するときのまとめ - Qiita

を参考に、prepareしてbindValueしてexecuteする書き方に改めつつ、
データベースへのアクセス全体をtry~catchで囲んで例外をキャッチできるようにした。

exit()で処理が抜けるのはあくまで製作途中ということで、
評価してみてほしい。

php

1<?php 2 3if (!isset($_POST['mail'] || !isset($_POST['pass']))) { 4 exit('error'); 5} 6try { 7 $pdo = new PDO('mysql:host=example.jp;dbname=user_data;charset=utf8', 'user', 'password', 8 array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION) 9 ); 10 $stmt = $pdo->prepare('SELECT userid, email, password FROM user_tb WHERE email = :email'); 11 $stmt->bindValue(':email', $_POST['mail']); 12 $stmt->execute(); 13 $result = $stmt->fetchAll(); 14 if ($result === false) { 15 exit('fetch error'); 16 } 17 if ($result === array()) { 18 exit('pass'); 19 } 20 if (isset($result[0]['pass'])) { 21 if (password_verify($_POST['pass'], $passs[$i])) { 22 $_SESSION['id'] = $result[0]['userid']; 23 exit('login'); 24 } 25 else { 26 exit('pass'); 27 } 28 } 29 30 31 32} catch (PDOException $e) { 33 exit('sql:' . $e->message); 34}

signup.phpもガッチャガチャ引っ掻き回してみた。
これもあくまで机上デバッグで文法エラーが出ないだろうというところまで詰めただけ。

bindParamじゃなくbindValueを使ったり、

try~catchの使い方を変えたり、

$pdoを関数の引数に使って外にだしてもアクセスできるようにしたり、

全角空白でインデントしている箇所を直したり、

まだ納得していない部分として、
ra()で新しいユーザーIDを作っているみたいだけど、
データベース上に登録済みのを生成しているかもしれないので、
ユーザー登録する前に検証する処理を入れるべき。

php

1<?php 2 3function ra(){ 4 $len=""; 5 for( $i=0; $i<10; $i++ ){ 6 $len.=substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 10); 7 } 8 return $len; 9} 10 11function newusers( $pdo, $userids ) { 12 $kuserid = ra(); 13 if (strpos($userids, $kuserid) !== false) { 14 newusers(); 15 } else { 16 $name = filter_input(INPUT_POST, 'name'); 17 $email = filter_input(INPUT_POST, 'email'); 18 $pass1 = filter_input(INPUT_POST, 'password'); 19 $pass2 = filter_input(INPUT_POST, 'password2'); 20 $niti = date("Y/m/d H:i:s"); 21 $pdo->beginTransaction(); 22 $stmt = $pdo->prepare("INSERT INTO user_tb (name, password,password2,userid,createddate,email) VALUES (:name, :password,:password2,:userid,:createddate,:email)"); 23 $pass1s = password_hash($pass1, PASSWORD_DEFAULT);//ここでハッシュ化 24 $pass2s = password_hash($pass2, PASSWORD_DEFAULT);//ここでハッシュ化 25 $stmt->bindValue(':name', $name, PDO::PARAM_STR); 26 $stmt->bindValue(':password', $pass1s, PDO::PARAM_STR); 27 $stmt->bindValue(':password2', $pass2s, PDO::PARAM_STR); 28 $stmt->bindValue(':email', $email, PDO::PARAM_STR); 29 $stmt->bindValue(':userid', $kuserid, PDO::PARAM_STR); 30 $stmt->bindValue(':createddate', $niti, PDO::PARAM_STR); 31 $stmt->execute(); 32 $pdo->commit(); 33 $_SESSION['id'] = $kuserid; 34 exit("ok"); // ここでphpの処理が抜けちゃうけどいいのかい? 35 } 36} 37 38function fu001 ( $pdo, $emails ) { 39 $email = $_POST['email']; 40 if (strpos($emails,$email) !== false) { 41 exit( "emailerror" ); 42 } else { 43 newusers($pdo, $userids); 44 } 45} 46 47 48$emails = ""; 49$userids = ""; 50try { 51 $pdo = new PDO('mysql:host=example.jp;dbname=user_data;charset=utf8','user','password', 52 array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION) 53 ); 54 55 $stmt = $pdo->query("SELECT * FROM user_tb"); 56 while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { // ここいらは何をやっているかわかんないから放置してる 57 $emails .= "[".$row["email"]."]"; 58 $userids .= "[".$row["userid"]."]"; 59 } 60 61 fu001($pdo, $emails); 62 //~~~省略~~~ 63 64 65 66 67}catch(PDOException $e){ 68 exit("spl"); 69}

投稿2019/11/12 13:02

編集2019/11/15 09:02
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Res

2019/11/13 08:33

アドバイスは嬉しいのですが回答でこれを言うには...
退会済みユーザー

退会済みユーザー

2019/11/13 09:28

全角空白を自分で見つけて直せるよう、VSCodeでもEclipseでもいいからちゃんと文法エラーを教えてくれるのを使うべきですよ。
Res

2019/11/13 12:01

その件は心配しないでください。
Res

2019/11/13 12:02 編集

>ユーザー登録する前に検証する処理を入れるべき。 もともと同じものにはならないと思います。
Res

2019/11/13 12:03

それより質問からあまりそれないでください。
Res

2019/11/15 09:24

はい。これから、しっかりと回答者側の負担も考え、しっかりと質問します。 今回の質問は申し訳ありませんでした。
guest

0

password_hashの第2引数に PASSWORD_DEFAULT を指定していますので、ハッシュ化した文字列は

$2y$10$4oa3dTCA7YAaYeBUmW5cpuXHQSdeO3pTrzRy/mDVaB.hh2fte1nlS

といったような、識別子$2y$から始まる60文字の文字列になります。
(PHP7.3の場合。デフォルト動作なので、文字数や識別子はバージョンによって変わる可能性はあります)

まずはuser_tb.password に上記の様な60文字の文字列が入っているか確認してみてください。
パスワードのハッシュは元パスワードより長い文字列になることが多いので、テーブルのカラム定義にもある程度の長さが必要です。

データベースに入っている内容が問題なさそうであれば

php

1<?php 2$password_hash = '$2y$10$4oa3dTCA7YAaYeBUmW5cpuXHQSdeO3pTrzRy/mDVaB.hh2fte1nlS'; 3$result = password_verify('password', $$password_hash); 4var_dump($result);

といったコードで検証できるので、確認してみてください。

  1. データがハッシュ文字列として正しくINSERTされている
  2. ログイン処理時にSELECTしてとってきた変数に正しいハッシュ文字列が入っている
  3. password_veriffyの第1引数が画面から入力したパスワード文字列、第2引数がDBに格納されているハッシュ文字列になっている

一つずつ確認して、どこまでうまく行っているのかを切り分けましょう。

PHP: password_hash - Manual

投稿2019/11/14 14:40

Eggpan

総合スコア3205

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

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

Res

2019/11/15 07:48

はい。 細かく説明していただいてありがとうございます。
guest

0

2019/11/13 21:44 で追加された方に回答

if ($resul ===array()){
$result
です

if ($resul ===array()){ exit('pass'); }exit($_POST['pass'].":". $result[0]['password']);

これだと
if ($resul ===array()){
の処理の後exitで終わってしまいます次の
if (password_verify($_POST['pass'], $result[0]['password'])) {
に行かないのでechoなどにしてください

投稿2019/11/14 00:55

date

総合スコア1820

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

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

退会済みユーザー

退会済みユーザー

2019/11/14 10:29

まさか、echoとexitを間違えて使っていた、なんてな(そんなことはあるはずが
Res

2019/11/15 07:27

安心してください!それは確認用のコードなので今はコメントにしてあります。 直していなくて申し訳ありません。
guest

0

コードは読む気にならんので、読まずに回答しています。

password_verify($pass,$passs[$i])の$passと$passs[$i]の中身の確認は行っています。

中身が適切なものなのであれば、password_verify() がおかしいです。古い php で、適当な関数を定義していませんか?

中身が適切になっていないのであれば、POST された password を加工しているどこかで問題が発生しています。変数の推移を確認し、意図したものになっているか検証してください。ハッシュ値への変換箇所と DB への登録箇所で適切な処理がなされていないケースをたまに見かけます。

投稿2019/11/12 23:06

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2019/11/13 00:31

$_POSTに格納している値を書き換えて、$_POSTに上書きするケースとかひどいのがあったよね
退会済みユーザー

退会済みユーザー

2019/11/17 06:44

なんで解決諦めたんだろ。。。 2箇所で変数確認すれば切り分け完了なのに^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問