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

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

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

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

Q&A

解決済

2回答

1181閲覧

ログイン機能でログインができない

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

0グッド

0クリップ

投稿2017/08/12 11:07

register_confirm.phpまではほぼ正常に動いているのを確認しました。
(メールを飛ばす部分はローカルサーバーなのでやっていません)
PHP Myadminでテーブルにデータの追加されているのが確認できているのに
ログインができません。ソースコードでおかしいところがありましたら
ご指摘お願いします。

register_submit.php

<?php require("function.php"); session_start(); header("Content-type: text/html; charset=utf-8"); //CSRFチェック if($_SESSION['token'] != $_POST['token']){ $_SESSION = array(); session_destroy(); session_start(); $_SESSION["error_status"] = 2; header("HTTP/1.1 301 Moved Permanently"); header("Location: login.php"); exit(); } //エラー情報のリセット $_SESSION["error_status"] = 0; $id = filter_input(INPUT_POST,'id'); $mail = $_POST["mail"]; $password = $_POST["password"]; //ソルト作成 $salt = get_salt(); //一時URLパスワード作成 $url_pass = get_url_password(); //ユーザー仮登録 //ストレッチングパスワード $hash = stretchedPassword($salt,$password); //データベース接続 $dsn = 'mysql:dbname=portfolio;host=localhost;charset=utf8mb4'; $user = 'root'; $password = ''; $dbh = new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); var_dump(isset($dbh)); //プレースホルダでSQL作成 $sql = "INSERT INTO USER (ID,SALT,PASSWORD,MAILADDRESS, TEMP_PASS,LAST_CHANGE_PASS_TIME,RESISTER_TIME)"; $sql .= "VALUES(?,?,?,?,?,?,?);"; var_dump(isset($sql)); //パラメータの型を指定 $stmt = $dbh->prepare($sql,array('text','text','text','text','text','timestamp','timestamp')); //パラメータを渡してSQL実行 $res = $stmt->execute(array($id,$salt,$hash,$mail,$url_pass,date('Y-m-d H:i:s'),date('Y-m-d H:i:s'))); //ID重複チェック ※ try{ }catch(PDOException $e){ die("接続失敗です{$e->getMessage()}"); $dbh = null; $_SESSION['error_status'] = 4; header("HTTP/1.1 301 Moved Permanently"); header("Location: register.php"); exit(); } $dbh = null; //ユーザーに確認メール送信 $mail = str_replace(["/r" , "/n"] , "" , $mail); $url = "http://" . SERVER . "/register_confirm.php?" . $url_pass; $msg = "以下のアドレスからアカウントを有効にしてください。" . PHP_EOL; $msg .= "アドレスの有効期限は10分間です。" . PHP_EOL; $msg .= "有効時間が過ぎたらパスワードのリセットをしてください" . PHP_EOL . PHP_EOL; $msg .= $url; mb_send_mail($mail,"ユーザー登録",$msg,"From:" . SENDER_EMAIL); ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <h1>仮登録完了</h1> 仮登録が完了しました。<br /> 登録を完了するには送信されたメールで手続きを行ってください。<br /> <a href="login.php">ログイン画面へ</a><br /> </body> </html>

register_confirm.php

<?php require_once("function.php"); session_start(); header("Content-type: text/html; charset=utf-8"); //URLからパラメータ取得 $url_pass = parse_url($_SERVER['REQUEST_URI'] , PHP_URL_QUERY); //ユーザー正式登録 $dsn = 'mysql:dbname=portfolio;host=localhost;charset=utf8mb4'; $user = 'root'; $password = ''; $dbh = new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //プレースホルダでSQL作成 $sql = "SELECT * FROM USER WHERE TEMP_PASS = ? AND RESISTER_TIME >= ?"; //パラメータの型を指定 $stmt = $dbh->prepare($sql,array('text' , 'timestamp')); // 10分前の時刻を取得 $date = new DateTime("- 10 min"); //パラメータを渡してSQL実行 $rs =$stmt->execute(array($url_pass , $date->format('Y-m-d H:i:s'))); $count = 0; while($row = $rs->fetch(PDO::ASSOC)){ $id = $row['id']; $count++; } if($count == 0){ //URLが不正か期限切れ $_SESSION["error_status"] = 3; header("HTTP1.1 301 Moved Permanently"); header("Location: register.php"); $dbh = null; exit(); } $sql = "UPDATE USER SET IS_USER = 1 WHERE ID = ? ;"; //パラメータの方を指定 $stmt = $dbh->prepare($sql , array('text')); //パラメータを渡してSQL実行 $stmt->execute(array($id)); $dbh = null; ?> <!DOCTYPE html> <html lang="ja"> <head> <body> <h1></h1> ユーザー登録完了しました。<br /> ログイン画面からログインしてください。<br /><br /> <a href="/login.php">ログイン画面に戻る</a> </body> </html> ?>

login.php

<?php // phpinfo(); require_once("function.php"); session_start(); header("Content-type: text/html; charset=urf-8"); ?> <style> a{ text-decoration:none; } input{ border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; } </style> <!DOCTYPE HTML> <html lang="ja"> <body> <h1>LOG IN</h1> <?php if($_SESSION["error_status"] == 1){ echo "<h2 style='color:red'>IDまたはパスワードが異なります</h2>"; } if($_SESSION["error_status"] == 2){ echo "<h2 style='color:red'>不正なリクエストです。</h2>"; } $_SESSION["error_status"] = 0; ?> <form action="login_check.php" method="post"> ID<br /><input type="text" name="id"><br /> PASS<br /><input type="password" name="password"><br /> <input type="submit" value="login"> <input type="reset" value="reset"><br /> </form> <a href="register.php">新規登録</a><br /> <a href="password_reset.php">パスワードリセット<br /> </body> </html>

login_check.php

<?php require_once("function.php"); session_start(); header("Content-type:text/html;charset=utf-8"); //パラメーター取得 $id = $_POST['id']; $password = $_POST['password']; // //ログイン判定 //DB接続 ※ $dsn = 'mysql:dbname=portfolio;host=localhost;charset=utf8'; $user = 'root'; $password = ''; $dbh = new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //プレースホルダでSQL作成 $sql= "SELECT * FROM USER WHERE ID =? AND IS_USER =1;"; //パラメータの型指定 $stmt = $dbh->prepare($sql,array('text')); //パラメータを渡してSQL実行 $rs = $stmt->execute(array($sql)); try { $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING)); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); exit; } $count = 0; while($row = $stmt->fetch()){ $id = $row["id"]; $salt = $row["salt"]; $db_password = $row["password"]; $reset = $row["reset"]; $count++; } $dbh = null; //ログイン失敗 if($count !=1){ $_SESSION["error_status"]=1; header("HTTP/1.1 301 Moved Permanently"); header("Location: login.php"); exit(); } //パスワードリセット対応 if($reset == 1){ $_SESSION["error_status"] =1; header("HTTP/1.1 301 Moved Permanently"); header("Location: login.php"); exit(); } //パスワード生成 $hash = stretchedPassword($salt,$pw); if($hash == $db_password){ //ログイン成功 //セッション ID振り直し session_regenerate_id(true); //セッションにID格納 $_SESSION['id']=$id; //CSRFのトークン作成 $_SESSION["token"] = $get_csrf_token(); //DB接続 $dsn = 'mysql:dbname=portfolio;host=localhost;charset=utf8'; $user = 'root'; $password = ''; $dbh = new PDO($dsn,$user,$pass); $dbh->setAttrbute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //プレースホルダでSQL作成 $sql = "UPDATE USER SET LAST_LOGIN_TIME = ? WHERE ID = ?"; //パラメータの型を指定 $stmt = $dbh->prepare($sql,array('timestamp','text')); //パラメータを渡してSQL実行 $stmt->execute(array(date('Y-m-d H:i:s'),$id)); $dbh = null; //リダイレクト header("HTTP/1.1 301 Moved Permanently"); header("Location: welcome.php"); }else{ $_SESSION["error_status"]=1; header("HTTP/1.1 301 Moved Permanently"); header("Location: login.php"); } ?>

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

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

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

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

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

guest

回答2

0

ベストアンサー

login.php

<a href="register.php">新規登録</a><br />
の中身は問題ない(register_submit.phpがどこからも呼ばれていない・参照されていないですが、
その先のregister_confirm.phpまで正常動作らしいので…)と仮定して…

試してもいませんし、パッと見で気になったのは、以下の点でしょうか。

○login_check.php
⇒DB接続時のパスワードの記載がない。
恐らくNGです。

PHP

1$password = ''; 2$dbh = new PDO($dsn,$user,$pass);

⇒SQLの実行結果($rs)が全く参照されていない。
(「while($row = $stmt->fetch()){」が「while($row = $rs->fetch()){」?)

⇒(可能性として)USERテーブルがIDに対して複数レコード存在している。($count++;で$countが2以上になる場合)
※register_submit.phpで重複チェックをしていない(DB任せ?)ため、プログラムからでは読み取れない。

○その他
$_SESSION["error_status"]の3,4に対しての処理がない。

(とりあえず、見るの辞めましたが)
上記のようなバグは、製造者のコーディング思想がブレているのが原因なので、かなり見にくいです。
MVCではないのも見にくい原因です。

とりあえず、製造者の傾向として、変数1つ1つの命名ルールがあいまいで、
動かなかったからその場しのぎで微修正・・・を繰り返している・・・ようなソースに見えました。
まずは、変数1つ1つを設計通り意図した使い方をしているか、
検索しながらコードチェックするか、作り直した方が早いかもしれません。

投稿2017/08/12 15:05

編集2017/08/12 16:19
tomari_perform

総合スコア760

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

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

退会済みユーザー

退会済みユーザー

2017/08/13 00:56

夜遅くに恐縮ですm(_ _)m dbのパスワードは、 mysqlのほうであえてからにしてあります。 (これは昨日再確認しました)sqlの実行結果が全く参照されてない事、重複結果をしてない事、error_status3、4に対しての処理がないことに関しては ぼくも何となく感じていました。データベースに接続するところがpearで書かれた手本だったので、まずはそこをpdoに自分で書き直しました。 このコードを修正して提出できるようにするにはかなり書き換えないとだめそうですね・・・どうするかしばらく考えます…。
tomari_perform

2017/08/13 01:10

yuus2733さんの書いたプログラムではないようなので、 正直に記載しますが、私なら全部作り変えちゃいます(汗)。 細かい経緯は不明ですが、パッと見の不具合の原因が「製造時のブレ」なので、 バグなく修正してリリースするためには、「全て見直しが必要」になるので。。。 (大した量ではないので)それをするくらいなら、 自分で0から作ってしまった方が早いです。 (ついでに、MVC化もしちゃいます。)
退会済みユーザー

退会済みユーザー

2017/08/13 02:36

charset とかもブレちゃってますね^^; 学習用ならともかく、実使用には耐えられないっぽいです。 私も作り直しに一票です。 login 機能の基本実装は以下が分かりやすかったです。 http://qiita.com/ShibuyaKosuke/items/f114ffccf441edb2b745
退会済みユーザー

退会済みユーザー

2017/08/13 03:53

いつもありがとうございます! charsetのところはいくつかのサイト回って書き換えてたので書き換えないまま投稿しちゃったものですねー... 統一するように気をつけます。
guest

0

login_check.php で
取得したパスワードを格納する変数をクリア(もしくは変更)していますね

PHP

1$password = $_POST['password'];2// //ログイン判定 3//DB接続 ※ 4$dsn = 'mysql:dbname=portfolio;host=localhost;charset=utf8'; 5$user = 'root'; 6$password = '';

投稿2017/08/12 15:46

kurosawa

総合スコア780

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

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

退会済みユーザー

退会済みユーザー

2017/08/13 01:55

ということは、$userの下の物も $password=$_['POST']; とするべきなのでしょうか? 変数を再定義してるから強制消去する結果になっているということでしょうか…
kurosawa

2017/08/13 04:03

いいえ、 DB接続のIDとパスワードとログインのID・パスワードを混同されてます。 それぞれ別の変数にしましょう。 register_submit.php も同様ですね。 画面から入力させたパスワードを一時URLに利用してますが こちらは $hash置換後、一度も利用していないから問題になっていないだけです。 まずはソース1行1行の意味や目的を理解しながら進めていくことが必要です (偉そうですみません) メール送信の箇所もコメントアウトしてますか? このままだとローカル環境でもメールが飛ぶので 他人メアドでのテストは注意してくださいませ。
退会済みユーザー

退会済みユーザー

2017/08/13 05:11

はい、変数変更とメール送信部分のコメントアウトしてみます。 変数は普通db接続部分を$passwordとしますか? ポストの方は$userpassとでもしておきましょうか…と思ってます
退会済みユーザー

退会済みユーザー

2017/08/13 08:34

ご指摘の変数の混同、メール送信部のコメントアウトしました。 ですがやはりログインできません。データベースには入ってるんですけどね・・・。色々噛み合わない部分があるのでしょう。。。 他の方も言っておられる通り、別の物を参考にしてみます。
kurosawa

2017/08/15 14:54 編集

そうですね。 まず、私ならどうするか?ですが 大まかな処理概要を整理します。 (今回の事例をもとに私なりに分解、整理して見ました) ログイン機能  ・新規会員登録 <index.html>   ・会員ID(メールアドレス)を入力させる    IDは会員を識別するのでメールアドレスの入力・カラムは不要とする  ・新規会員登録 <register_submit.php>   ・会員IDのメアドパターンチェック   ・時限パスを生成(サイト固定サルト+ランダム+暗号化)   ・DB仮登録    ・会員IDと時限パスと仮会員(0)でセット   ・メール送信    ・本登録画面のリンクを表記(register_confirm.php?時限パスで送信する)  ・本会員登録 <register_confirm.php>   ・クエリから時限パス取得   ・時限パスでDB検索(存在しないor時間超過ならエラー)   ・追加の会員情報を入力させる   ・新パスワードハッシュ化   ・会員情報+本会員(1)で本会員登録  ・ログイン   ・セッション開始   ・CSRFチェック   ・DB検索    ・パスワードチェック(8~16字)    ・パスワードをハッシュ化    ・IDとハッシュPWで検索   ・セッションセット  ・会員削除(解除)   ・セッション開始   ・CSRFチェック   ・本会員(1)を解除(2)にセット とか、大まかに処理を分類し、それぞれの異常処理やエラートラップを 組み込んでいきます。 te2jiさんが提供してくれた http://qiita.com/ShibuyaKosuke/items/f114ffccf441edb2b745 なんかは非常に有意義な情報だと思います。
退会済みユーザー

退会済みユーザー

2017/08/16 13:20

丁寧に、しかも再度分解と要件定義のし直しまでありがとうございます。 要件定義など、上流工程と言われる部分は何をしているのか知りたいのですが、 どういう書籍やサイトを見ればわかるでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問