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

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

ただいまの
回答率

90.45%

  • PHP

    24634questions

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

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

解決済

回答 2

投稿

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

yuus2733

score 103

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");
}



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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

login.php

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

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

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

$password = '';
$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/13 09:56

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

    キャンセル

  • 2017/08/13 10:10

    yuus2733さんの書いたプログラムではないようなので、
    正直に記載しますが、私なら全部作り変えちゃいます(汗)。

    細かい経緯は不明ですが、パッと見の不具合の原因が「製造時のブレ」なので、
    バグなく修正してリリースするためには、「全て見直しが必要」になるので。。。

    (大した量ではないので)それをするくらいなら、
    自分で0から作ってしまった方が早いです。
    (ついでに、MVC化もしちゃいます。)

    キャンセル

  • 2017/08/13 11:36

    charset とかもブレちゃってますね^^;
    学習用ならともかく、実使用には耐えられないっぽいです。
    私も作り直しに一票です。

    login 機能の基本実装は以下が分かりやすかったです。
    http://qiita.com/ShibuyaKosuke/items/f114ffccf441edb2b745

    キャンセル

  • 2017/08/13 12:53

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

    キャンセル

+1

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/08/13 10:55

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

    キャンセル

  • 2017/08/13 13:03

    いいえ、
    DB接続のIDとパスワードとログインのID・パスワードを混同されてます。
    それぞれ別の変数にしましょう。

    register_submit.php も同様ですね。
    画面から入力させたパスワードを一時URLに利用してますが
    こちらは $hash置換後、一度も利用していないから問題になっていないだけです。

    まずはソース1行1行の意味や目的を理解しながら進めていくことが必要です
    (偉そうですみません)

    メール送信の箇所もコメントアウトしてますか?
    このままだとローカル環境でもメールが飛ぶので
    他人メアドでのテストは注意してくださいませ。

    キャンセル

  • 2017/08/13 14:11

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

    キャンセル

  • 2017/08/13 17:34

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

    キャンセル

  • 2017/08/15 23:53 編集

    そうですね。
    まず、私ならどうするか?ですが
    大まかな処理概要を整理します。
    (今回の事例をもとに私なりに分解、整理して見ました)

    ログイン機能
     ・新規会員登録 <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 22:20

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

    キャンセル

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

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

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

  • PHP

    24634questions

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