実現したいこと/ソースコード
ログインの認証時に、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}
情報
皆様、貴重なお時間を頂きこの質問に回答してくださり、誠にありがとうございました。
今回解決することはできませんでしたが、質問の仕方に対する指摘等を、大切なお時間を割いて回答していただき非常に感謝しております。
お忙しい中ありがとうございました。
forループの中でglobal宣言せず、予めforループの外で普通に変数を宣言しておけばいいんじゃないかな。
それってloginのverifyですか?
コード全体がないのとインデント全くないので見通せません。手元のコードから調整してコードもなるべく全体の流れがわかるコードで提示願います
globalを使った意図も説明願います
globalは前の時のコードの消し忘れです。あってもなくてもいいので残ってます。
インデントはできませんか?
難しければWeb上のコード整形サービスかコードフォーマット機能のあるエディタを利用してください。
読みづらいコードは問題切り分けを困難にします。(残っているglobalも同じく。なくて差し支えないなら早い段階で消すべき。)
すぐやります。
いつもインデントを消してしまう癖があるので.....
https://okuden-labo.com/home/php-code
できればEclipseなどコードフォーマット機能のあるエディタを使ってほしいです。
可読性の良し悪しはコードの品質にも直結します(それが趣味や学生であっても。回答者は読む気をなくす人が多いです)
質問者さんの思う「無関係」は第三者が検証してはじめて「無関係」と言えるものです。動かしているコードと違うコードを示されても、そこが問題なければ、示されていない箇所に問題があるとしか思えないので、より実態に近いものを示したほうが解決が近くなります。
改善してほしいところを書いてと言われましても、せっかくの回答者のコードを改悪して「できない」と言っている状況では書いてもらえる可能背は低く、ヘイトを集めるだけです。
厳密に言えば下記も質問要件とは関係ありません。あなたの個人的な想いです。
「11/13/21:37:
やってほしいことだけを記載した丸投げの質問と思うならば、なぜそうおもったのか。改善してほしいところを教えてください。 」
質問者さんの抱えている状況を第三者が再現して検証できる状況にならない限り、単なる丸投げ、無償デバッグ依頼にしかなりません。回答者に掛かる負担のことまで気持ちを配って、問題解決してもらおうと工夫することはできませんか? 現時点で質問者さんのコードと回答者のコードが別(無関係と言って省略している)であったり、データベースを利用しているのにデータベースに関する情報(mysqlとかpostgresqlとか、それらのバージョンとか、テーブル構造CREATE TABLE文とか、サンプルデータとか)が出てこない「いびつさ」も気になります。問題点を絞り込むために、質問者さんも回答側も同じデータベースを再現し、同じphpコードを動かし、検証して見る必要があります。解決につながる動きが必要なのは質問者さんなのに、全く動く気配がない。解決させようという気がないと思われてもしかたないのではないでしょうか。「無関係」と言い張っている以上、進展しませんよ。情報がない中で適当に動く(かもしれない)コードを回答者が示したところで不満なんでしょ?
ありがとうございます。言われたと通り情報を追記しました。
あまり質問にも慣れていないもので。
「問題」は質問者が認識している範囲だけとは限らないというのは分かりますか?
その部分の指摘を「無関係」と切り捨てるおつもりなら得られるアドバイスはありませんし、今の問題すら解決はしません。
あとちょこちょこ言い訳を挟んでこられるのでアドバイスが受け入れられるか疑問で、余計にアドバイスを得られる機会を失しています。
回答者はあなたより沢山の経験をしているし技術も知見も持っています。
既に指摘されているかもしれませんが、「関係ない」と判断できるだけの経験も知見もお持ちなのですか?でしたらなぜ質問したのですか?
繰り返すようですが、「自分が思ってることだけ解決すればいい」という自己中心的な考え方だと誰も手をさしのべません。
解決する気がないと見ている人は認識します。(View数が多いのはどこかに悪い質問例ということで晒されてるんでしょうね)
> View数が多いのはどこかに悪い質問例ということで晒されてるんでしょうね
自分の知る範囲だと数か所に貼られてそれが拡散されている感じですね
テーブル構造を見せてほしいというのはもしかしたらpasswordカラムとかがINT(11)とかVARCHAR(12)とかになってて、passwordにデータがちゃんと入っていないかもしれない。
とかがあるから聞いています
100%無関係と断定できます。
その部分を載せるとセキュリティ上よくないからです。
全て載せれるというわけには申し訳ありませんがいけません。
>100%無関係と断定できます。
どこがでしょうか。根拠がわかりません。
現にm6uさんのアドバイスを突っぱねています。私は無関係には思えません。コードの見やすさ、デバッグのしやすさはプログラミングする上では全て関係してきます。品質はもちろん、その人の頭がきちんと整理できているかとか、様々なことが見えてきます。
それを無関係となぜ言えますか?
「コード読む気にならん」という意見もあるなかでなぜ無関係と言い切れますか?
コード読んでもらえないのになぜ解決できると言い切れますか?
>その部分を載せるとセキュリティ上よくないからです。
といったように申し訳ありませんが「絶対」追記できません。
データならともかくテーブル定義で問題になることってそうそうないと思いますね。
もしセキュリティリスクを考慮するなら求められているカラムだけでもいいし、そもそもこのような危ない実装をしているというのを全世界に発信しているというほうがリスク高いです。
明かせないリアル情報なんて要りません。
teratail上で必要なことは、質問者と回答者側との間に、
テストや検証用にミニマルなphpコードと、テーブルのテスト用データがあればいいのです。
それで動いたという礎(証左)を元に、本番データに近いものでテストするのです。
(付き合ってやりたいが、こっちも本業があるものでな。)
>現にm6uさんのアドバイスを突っぱねています。
>質問者さんの抱えている状況を第三者が再現して検証できる状況にならない限り
再現して検証できるよう、できる限りの情報を記載しました。
私のサイトはHTMLのみでバックグラウンドが見えるような素っ裸にしていいサイトではないです。
※「HTMLのみ」は見た目やコードの問題ではなくphpのようにユーザーに見えるかどうかをあらわしただけです。
もちろん回答者さんの「このままで解決できない」を私なりに今まで追記しました。
私は質問者なので回答者じゃありませんし、回答者の思うことは回答者に聞くしかありません。
今まで回答者を考えてください。とアドバイスをいただきましたが、質問者の立場も少しは考えてくださるとありがたいです。私自身質問にすべてのソースコードを漏らしたくないのでいっています。
私は回答者の意見を積極的に取り入れ質問を改善したつもりです。私なりに改善しました。
上から目線で申し訳ありません。
>実装をしているというのを全世界に発信しているというほうがリスク高いです。
それはいえてます。今はテスト段階なので構わないです。
この「VIEW 530」の中に不審者がいなければいいですけど...
>私のサイトはHTMLのみのような素っ裸にしていいサイトではないです。
ならphpのコードすら出すべきではないですね。攻撃してくれって言ってるようなもんです。
それに本当に現在のような実装なら「私のサイトは~」と高らかと歌い上げて良い素晴らしい作りにはなってないと思いますが。
HTMLのみのサイトでも素晴らしい作りにはできますし、あまり不特定多数をディスるような発言はされない方が良いかと。
既に加熱しているヘイトに爆弾を追加するだけです。
>この「VIEW 530」の中に不審者がいなければいいですけど...
なら、運営に依頼して削除してもらうべきですね。
ログインしてなくても見れるので世界中からアクセス可能です。
私は詳しくないですがview数増やさないように閲覧できる手段もあるんじゃないですかね。
はい...
>それに本当に現在のような実装なら「私のサイトは~」と高らかと歌い上げて良い素晴らしい作りにはなってないと思いますが。
今はテスト段階なので構わないです。
teratailの運営のようにいろいろと詳しくありがとうございます。
>私は詳しくないですがview数増やさないように閲覧できる手段もあるんじゃないですかね。
確かにそうですね。思ってもいませんでした。
>ならphpのコードすら出すべきではないですね。攻撃してくれって言ってるようなもんです。
今回はしょうがないです。
>設計も含めて全部書き直さなきゃどうにもならないレベル
正解です。でも全部は無理なのでまた書き直して、詰まってしまったところでまた質問を出そうと思います。
>正解です
わざとやってますか?正解と思うならそんなコードそもそも出さないでください。
ヘイトを集めたいだけなら今後は誰からもアドバイスを得られないと思ってください。
>今はテスト段階なので構わないです。
では出してはいけない項目などそうそうないでしょう。
>では出してはいけない項目などそうそうないでしょう。
テスト段階でもじき公開します
>わざとやってますか?
正解とはm.ts10806さんが「設計も含めて全部書き直さなきゃどうにもならないレベル」と言ったことに確信したということ。以上です。
あまり聞きださないでください。
login.phpであるとしたらもしかしたら、input nameはname="pass"じゃないかもしれないとかあるかもしれないので、ログインのhtmlはみせていいのでは、見せないのなら私はここまでです
後一応ですが、今のプログラムだと同じemailがあったら一番初めに登録したemailとパスワードを参照している。テーブル内に同じemailがもしあったら、その時に登録したパスワードじゃないと認証しません
同じemailがあるかどうかみてみてはどうですか
そうですか。では、なにも聞きません。お一人で悩んでください。
質問は削除依頼を運営に出しておいてくださいね。
もうじき公開するものを「テスト」とは表現しませんし、「こんなコード書いてて公開します!」と世界に向けて発信しているわけですから。
ブラウザから確認できない情報を1文字ですら出すべきではないでしょう。
(それにハッキリ言うと今の質問者さんの姿勢を貫く限り1年後に設計含めて劇的に改善されているとは思えない)
まだPHP初めて数か月です、、まだまだ勉強して公開したいと思います。
あとじきの表現はまだ先を指しているつもりです。
>もうじき公開するものを「テスト」とは表現しませんし
はい。テストからそのまま改良していくつもりで、今は「テスト」の段階ということです。
説明不足で申し訳ないです。
公開するのは一旦頭から外して基礎とセキュリティを叩き込んでください。
あと質問の仕方、回答者とのコミュニケーションの取り方も改善してください。
どう見ても回答者からアドバイスを引き出せるようなやり方をしていません。ヘイトを集めてばかりです。
プログラミング初心者ならまだしもコミュニケーション初心者では話になりません(プログラミング経験はほぼ関係ない)。
初めて数ヵ月で何の根拠や自信があって言い切ってるのか知りませんが、出して問題がある情報がそんなにあるものではないですよ?
業務で使っていて顧客情報預かってるとかそういうことかと思ったら初めて数ヵ月が作るログイン認証ですか。
出しちゃいけないのはサーバーIPとかドメインとかDB接続情報くらいのもんじゃないですか(あとは自身の個人情報)。
誰も名前や住所や電話番号教えろなんて言ってません。
ので、テーブル定義やhtml程度が出せない理由はどこにもないですね。しかもそのなかで1つのカラムだけ。
絶対的な独自のサービスが構想にあったとしてもこの内容でそれが現れるようなものではありません。
このコードだって完全独自に組み上げたものではないでしょう?
変に意固地にならず応じていれば投稿して数時間で解決していてもおかしくない内容です。こじれたことは自身が原因と猛省して臨むくらいじゃないと5年10年経っても公開できるものはできませんよ。
>変に意固地にならず
最初回答者が言っていることがあまり理解できず、こんがらがってしまいました。
まだ私自身未成年ですし、まだ学ばなければいけないことも多いと思います。
m.ts10806さんの思っていることをしっかりと理解し今後に役立てていこうとおもいます。
今回の質問でご迷惑をおかけして申し訳ありませんでした。
>未成年ですし
先に指摘したように言い訳して逃げる姿勢が問題を大きくしているだけです。
理解できないなら聞くべきです。質問に初心者アイコンでもつけておけばそれだけでも伝わるし、内容から初心者であることは誰の目にも明らかです。聞き方含めた対応の仕方すら間違えなければ「そんなことも知らないのか?」と責められることもないでしょう。
間違えた結果がこれです。
それに大事なのは、問題を投げ掛けたなら解決するまで対応するのが質問者の責任です。年齢や性別、国や地域、経験も関係ありません。
迷惑かける可能性があるのはteratailユーザーやteratail運営ではなく(そりゃ他人の時間使っていることは配慮すべきだけど)、あなたが公開するサイトを利用するであろう人たちです。
はい。しっかりと頭に叩き込んでおきます。最後の最後まで本当にご迷惑をおかけして申し訳ありません。そして、たくさんの指導。ありがとうございます。
(2回目)
それに大事なのは、問題を投げ掛けたなら解決するまで対応するのが質問者の責任です。
要約:
解決してないなら引き下がろうとするな。
> まだ私自身未成年ですし、まだ学ばなければいけないことも多いと思います。
いや、俺だって未成年だよ
asuchi0819さん
マジすか(ここ最近でトップ3くらい驚いたかもしれない)
m.ts10806さん
マジっすね
でも未成年でもここまで知識がつけられたのはm.ts10806さんなどのteratailの回答者さん方のおかげです、
asuchi0819さん
ここで言うことではないかもしれませんが、そう言ってくれて嬉しいですね。
回答者続けてきた意味があります。