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

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

ただいまの
回答率

87.34%

意図しないアカウントでログインしてしまう

解決済

回答 2

投稿

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

score 46

前提・実現したいこと

メールアドレスとパスワードでログインする機能を作っています。
ログイン後、home.phpへ移動しますが、出力されるアカウントが違うアカウントでログインしたことになってしまいます。

1@gmail.comと正しいパスワードでログインすると他のアカウントの2@gmail.comでログインしたことになっています。
どのアカウントでログインしても2@gmail.comでログインしたことになってしまいます。
ログイン画面(login.php)->ログイン後のホーム画面(home.php)->ログアウト(logout.php)

ログアウトが原因なのかとも思いましたが、原因がわからずにいます。

該当のソースコード

<login.php>
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);
ob_start();
session_start();

if( isset($_SESSION['user']) != "") {
  header("Location: home.php");
}
try {
  $db['host'] = "localhost";  
  $db['user'] = "root";  
  $db['pass'] = "";  
  $db['dbname'] = "reserve";  

  // エラーメッセージの初期化
  $errorMessage = "";

  if (isset($_POST["login"])) {
      if (empty($_POST["shop_email"])) {
          $errorMessage = 'メールアドレスが未入力です。';
      } else if (empty($_POST["shop_password"])) {
          $errorMessage = 'パスワードが未入力です。';
      }

      if (!empty($_POST["shop_email"]) && !empty($_POST["shop_password"])){
          // 入力したユーザIDとパスワードを格納
          $shop_email = $_POST["shop_email"];
          $shop_password = $_POST["shop_password"];

          // 2. ユーザIDとパスワードが入力されていたら認証する
          $dsn = sprintf('mysql: host=%s; dbname=%s;', $db['host'], $db['dbname']);
          $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_EMULATE_PREPARES,false));
      }
      $query = "SELECT * FROM shop WHERE shop_email=:shop_email";
      $stmt = $pdo->prepare($query);
      $stmt->bindValue(":shop_email",$shop_email, PDO::PARAM_INT);
      $stmt->execute();

      //パスワード(暗号化済み)とユーザーIDの取り出し
      $row = $stmt->fetch(PDO::FETCH_ASSOC);
      $db_hashed_pwd = $row['shop_password'];
      $shop_id = $row['shop_id'];


      // ハッシュ化されたパスワードがマッチするかどうかを確認
    if (password_verify($shop_password, $db_hashed_pwd)) {
      $_SESSION['user'] = $shop_id;
      header("Location:home.php");
      exit;
    } else { ?>
      <div class="alert alert-danger" role="alert">電話番号とパスワードが一致しません。</div>
    <?php }
  }

} catch (PDOException $e) {
   var_dump($e);
   die();
}
?>
<!DOCTYPE HTML>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>店舗ログインページ</title>
  </head>
  <body>
    <div class="main" >
      <div class="container" >
        <div class="row">
          <div class="col-sm-10 offset-sm-1" style="padding-bottom:50%;background-color:rgb(237, 237, 237);">
            <form name="loginForm" method="post">
              <div class="form">
                <p class="alert alert-success" style="text-align:center;">ログインフォーム</p>

                <div class="form-group">
                  <label for="shop_email">メールアドレス</label><br>
                  <input type="email"  class="form-control" name="shop_email" placeholder="メールアドレス" required />
                </div>

                <div class="form-group">
                  <label for="shop_password">パスワード</label><br>
                  <input type="password" class="form-control" name="shop_password" placeholder="パスワード" required />
                </div>

                <button type="submit" class="btn btn-success" name="login">ログインする</button>

              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
<home.php>
<?php
error_reporting(E_ALL);
ini_set("display_errors",1);

try {
  session_start();
  $pdo = new PDO('mysql:host=localhost;dbname=reserve;charset=utf8','root','',);
  $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  if(!isset($_SESSION["user"])) {
    header("Location: shop_index.php");
  }

  // ①ユーザーIDからユーザー名を取り出す
  $query = "SELECT * FROM shop WHERE shop_id=:shop_id";
  $shop_stmt = $pdo->prepare($query);
  $shop_stmt->bindValue(':shop_id', $_SESSION['user'], PDO::PARAM_INT);
  $shop_stmt->execute();

  // ショップ情報の取り出し
  $row = $shop_stmt->fetch(PDO::FETCH_ASSOC);
  $shop_id = $row['shop_id'];
  $shop_name = $row['shop_name'];
  $shop_email = $row['shop_email'];

} catch (PDOException $e) {
   var_dump($e);
   die();
}

?>
<!DOCTYPE HTML>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>店舗トップ</title>
  </head>

  <body>
    <div class="main">
      <div class="container" style="">
        <div class="row">
          <div class="col-xl-12" style="">
            <div class="main-right">
              <div class="container" >
                <div class="login" >
                  <p ><?php echo htmlspecialchars($shop_name, ENT_QUOTES, 'UTF-8'); ?></p>
                  <a href="logout.php?logout" >ログアウト</a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
<logout.php>

<?php
session_start();

// logout.php?logoutにアクセスしたユーザーをログアウトする
if(isset($_GET['logout'])) {
  session_destroy();
  unset($_SESSION['user']);
  header("Location:login.php");

}


イメージ説明

補足情報(FW/ツールのバージョンなど)

開発環境 XAMPP
windows10
phpmyadmin 4.8.5
Apache/2.4.39 (Win64) OpenSSL/1.1.1b PHP/7.3.5

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2019/06/03 20:01

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

0

下の部分がおかしいのでSELECT * FROM shop WHERE shop_email=0が流れて全レコード取得してますね。

$query = "SELECT * FROM shop WHERE shop_email=:shop_email";
$stmt = $pdo->prepare($query);
$stmt->bindValue(":shop_email",$shop_email, PDO::PARAM_INT);
$stmt->execute();


$stmt->debugDumpParams(); とかすれば分かると思います。


余談になりますけど、
先に関数にまとめたほうが良いと思います。

この行数で1ファイルで同じコードコピーではもうデバッグできないのではないかと・・。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/03 23:09

    ありがとうございます。
    [37] SELECT * FROM shop WHERE shop_email=0 Params: 1 Key: Name: [11] :shop_email paramno=-1 name=[11] ":shop_email" is_param=1 param_type=1

    確かに0になっていたのですが、var_dump($shop_email);をやるとメールアドレスは入っているのですがなぜ0になってしまうのでしょうか?

    キャンセル

  • 2019/06/03 23:30

    $shop_emailは数値としてSQLを作成するよう、プログラムに書いているからです。

    キャンセル

  • 2019/06/03 23:55

    解決できました!
    ありがとうございます!

    キャンセル

0

ログアウトを行ったあと、Cookiesとキャッシュデータを全削除して
別ユーザーでログインしたときに成功して、
全削除しないで別ユーザーでログインしたとき元のユーザーで表示される場合には、
コンテンツがキャッシュされていてそれを表示しています。
そのときにHTTPヘッダーでリダイレクトされても、
home.phpを以前読み込んだことがあって
コンテンツの有効期限内だとすると
webサーバーにリクエストせずキャッシュを表示してしまうのです。

本当にそうかを確認するのに、
例えばFirefoxならHTTP Live Headerというアドオンを使って
HTTPヘッダーのやり取りを観察するとかすればいいです。

【回避案、その1】
webコンテンツの有効期限を適切に設定すると良いかも。
head要素の中にmeta要素でExpires指定するなど。
HTMLタグ/ページ全般タグ/キャッシュの有効期限を指定する - TAG index

【回避案、その2】
webコンテンツの有効期限を適切に設定すると良いかも。
webサーバーがapache httpdであれば
mod_expires - Apache HTTP サーバ バージョン 2.4
を駆使してみるなど。

【回避案、その3】
login.phpやhome.phpとせず、
urlの後ろにランダムな数字をもたせてキャッシュを働かせないとか。
login.php?random=1565746547974865
とか。

もしかしたらもっとスマートな方法があるかもしれない。
「コンテンツの有効期限」「有効期限」「Expires」などでネット検索すると
ヒントが見つかりそう。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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