回答編集履歴

2 修正

s8_chu

s8_chu score 14621

2016/12/20 22:51  投稿

セキュリティとかはできるだけ質問者さんのコードのままにしておきたいのでおいておいて、このようにすれば動くのではないでしょうか。
```PHP
<?php
session_start();
$db['host'] = "localhost"; // DBサーバのURL
$db['user'] = "root"; // ユーザー名
$db['pass'] = "3141592653589793238462643383279"; // ユーザー名のパスワード
$db['pass'] = "pass"; // ユーザー名のパスワード
$db['dbname'] = "loginManagement"; // データベース名
$errorMessage = "";
// ログインボタンが押された場合
if (isset($_POST["login"])) {
   // 1. ユーザIDの入力チェック
   if (empty($_POST["mailaddress"])) { // emptyは値が空のとき
       $errorMessage = 'ユーザーIDが未入力です。';
   } else if (empty($_POST["password"])) {
       $errorMessage = 'パスワードが未入力です。';
   }
   if (!empty($_POST["mailaddress"]) && !empty($_POST["password"])) {
       // 入力したユーザIDを格納
       $mailaddress = $_POST["mailaddress"];
       // 2. ユーザIDとパスワードが入力されていたら認証する
       $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']);
       // 3. エラー処理
       try {
           $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
           $stmt = $pdo->prepare('SELECT * FROM userData WHERE mailaddress = :mailaddress');
           $stmt->execute(array(":mailaddress" => $mailaddress));
           $password = $_POST["password"];
           if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
               if (password_verify($password, $row['password'])) {
                   session_regenerate_id(true);
                   $_SESSION["USERID"] = $row['mailaddress'];
                   header("Location: Main.php"); // メイン画面へ遷移
                   exit(); // 処理終了
               } else {
                   // 認証失敗
                   $errorMessage = 'ユーザーIDあるいはパスワードに誤りがあります。';
               }
           } else {
               // 4. 認証成功なら、セッションIDを新規に発行する
               // 該当データなし
               $errorMessage = 'ユーザーIDあるいはパスワードに誤りがあります。';
           }
       } catch (PDOException $e) {
           $errorMessage = 'データベースエラー';
           //$errorMessage = $sql;
           // $e->getMessage() でエラー内容を参照可能(デバック時のみ表示)
           // echo $e->getMessage();
       }
   }
}
?>
<!doctype html>
<html>
<head>
   <meta charset="UTF-8">
   <title>ログイン</title>
</head>
<body>
<h1>ログイン画面</h1>
<!-- $_SERVER['PHP_SELF']はXSSの危険性があるので、actionは空にしておく -->
<!-- <form id="loginForm" name="loginForm" action="<?php print($_SERVER['PHP_SELF']) ?>" method="POST"> -->
<form id="loginForm" name="loginForm" action="" method="POST">
   <fieldset>
       <legend>ログインフォーム</legend>
       <div><font color="#ff0000"><?php echo $errorMessage ?></font></div>
       <label for="mailaddress">ユーザーID</label><input type="text" id="mailaddress" name="mailaddress"
                                                     placeholder="ユーザーIDを入力"
                                                     value="<?php if (!empty($_POST["userid"])) {
                                                         echo htmlspecialchars($_POST["userid"], ENT_QUOTES);
                                                     } ?>">
       <br>
       <label for="password">パスワード</label><input type="password" id="password" name="password" value=""
                                                 placeholder="パスワードを入力">
       <br>
       <input type="submit" id="login" name="login" value="ログイン">
   </fieldset>
</form>
<br>
<form action="SignUp.php">
   <fieldset>
       <legend>新規登録フォーム</legend>
       <input type="submit" value="新規登録">
   </fieldset>
</form>
</body>
</html>
```
ちなみに、メールアドレスでの登録ということは、新規登録のときに[filter_var関数](http://php.net/manual/ja/function.filter-var.php)などで**ユーザーが入力した文字列がメールアドレスの形式なのかチェックする**必要があると思います。質問者さんはこちらもリンクしているページの新規登録を参考にしていると思うので、メールアドレスのチェックを加えたコードを以下に書いておきます。
```PHP
<?php
session_start();
$db['host'] = "localhost"; // DBサーバのURL
$db['user'] = "root"; // ユーザー名
$db['pass'] = "pass"; // ユーザー名のパスワード
$db['dbname'] = "loginManagement"; // データベース名
// エラーメッセージ、登録完了メッセージの初期化
$errorMessage = "";
$SignUpMessage = "";
// ログインボタンが押された場合
if (isset($_POST["signUp"])) {
   // 1. ユーザIDの入力チェック
   if (empty($_POST["mailaddress"])) { // 値が空のとき
       $errorMessage = 'mailaddressが未入力です。';
   } else if (empty($_POST["password"])) {
       $errorMessage = 'パスワードが未入力です。';
   } else if (empty($_POST["password2"])) {
       $errorMessage = 'パスワードが未入力です。';
   }
   if (!empty($_POST["mailaddress"]) && !empty($_POST["password"]) && !empty($_POST["password2"]) && $_POST["password"] == $_POST["password2"] && filter_var($_POST['mailaddress'], FILTER_VALIDATE_EMAIL)) {
       // 入力したユーザIDとパスワードを格納
       $mailaddress = $_POST["mailaddress"];
       $password = $_POST["password"];
       // 2. ユーザIDとパスワードが入力されていたら認証する
       $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']);
       // 3. エラー処理
       try {
           $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
           $stmt = $pdo->prepare("INSERT INTO userData(mailaddress, password) VALUES (?, ?)");
           $stmt->execute(array($mailaddress, password_hash($password, PASSWORD_DEFAULT))); // パスワードのハッシュ化を行う(今回は文字列のみなのでbindValue(変数の内容が変わらない)を使用せず、直接excuteに渡しても問題ない)
           $userid = $pdo->lastinsertid(); // 登録した(DB側でauto_incrementした)IDを$useridに入れる
           $SignUpMessage = '登録が完了しました。あなたの登録ユーザIDは ' . $userid . ' です。パスワードは ' . $password . ' です。'; // ログイン時に使用するIDとパスワード
       } catch (PDOException $e) {
           $errorMessage = 'データベースエラー';
           // $e->getMessage() でエラー内容を参照可能(デバック時のみ表示)
           // echo $e->getMessage();
       }
   } elseif ($_POST["password"] != $_POST["password2"]) {
       $errorMessage = 'パスワードに誤りがあります。';
   } elseif (filter_var($_POST['mailaddress'], FILTER_VALIDATE_EMAIL) == false) {
       $errorMessage = 'メールアドレスの書式が間違っています。';
   }
}
?>
<!doctype html>
<html>
<head>
   <meta charset="UTF-8">
   <title>新規登録</title>
</head>
<body>
<h1>新規登録画面</h1>
<!-- $_SERVER['PHP_SELF']はXSSの危険性があるので、actionは空にしておく -->
<!-- <form id="loginForm" name="loginForm" action="<?php print($_SERVER['PHP_SELF']) ?>" method="POST"> -->
<form id="loginForm" name="loginForm" action="" method="POST">
   <fieldset>
       <legend>新規登録フォーム</legend>
       <div><font color="#ff0000"><?php echo $errorMessage ?></font></div>
       <div><font color="#0000ff"><?php echo $SignUpMessage ?></font></div>
       <label for="mailaddress">ユーザー名</label><input type="text" id="mailaddress" name="mailaddress"
                                                    placeholder="ユーザー名を入力"
                                                    value="<?php if (!empty($_POST["mailaddress"])) {
                                                        echo htmlspecialchars($_POST["mailaddress"], ENT_QUOTES);
                                                    } ?>">
       <br>
       <label for="password">パスワード</label><input type="password" id="password" name="password" value=""
                                                 placeholder="パスワードを入力">
       <br>
       <label for="password2">パスワード(確認用)</label><input type="password" id="password2" name="password2" value=""
                                                       placeholder="再度パスワードを入力">
       <br>
       <input type="submit" id="signUp" name="signUp" value="新規登録">
   </fieldset>
</form>
<br>
<form action="Login.php">
   <input type="submit" value="戻る">
</form>
</body>
</html>
```
1 修正

s8_chu

s8_chu score 14621

2016/12/20 22:50  投稿

セキュリティとかはできるだけ質問者さんのコードのままにしておきたいのでおいておいて、このようにすれば動くのではないでしょうか。
```PHP
<?php
session_start();
$db['host'] = "localhost"; // DBサーバのURL
$db['user'] = "root"; // ユーザー名
$db['pass'] = "pass"; // ユーザー名のパスワード
$db['pass'] = "3141592653589793238462643383279"; // ユーザー名のパスワード
$db['dbname'] = "loginManagement"; // データベース名
$errorMessage = "";
 
// ログインボタンが押された場合
if (isset($_POST["login"])) {
   // 1. ユーザIDの入力チェック
   if (empty($_POST["userid"])) { // emptyは値が空のとき
   if (empty($_POST["mailaddress"])) { // emptyは値が空のとき
       $errorMessage = 'ユーザーIDが未入力です。';
   } else if (empty($_POST["password"])) {
       $errorMessage = 'パスワードが未入力です。';
   }
   if (!empty($_POST["userid"]) && !empty($_POST["password"])) {
   if (!empty($_POST["mailaddress"]) && !empty($_POST["password"])) {
       // 入力したユーザIDを格納
       $userid = $_POST["userid"];
       $mailaddress = $_POST["mailaddress"];
       // 2. ユーザIDとパスワードが入力されていたら認証する
       $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']);
       // 3. エラー処理
       try {
           $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
           $stmt = $pdo->prepare('SELECT * FROM userData WHERE mailaddress = :mailaddress');
           $stmt->execute(array(":mailaddress" => $userid));
           $stmt->execute(array(":mailaddress" => $mailaddress));
           $password = $_POST["password"];
           if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
               if (password_verify($password, $row['password'])) {
                   session_regenerate_id(true);
                   $_SESSION["USERID"] = $row['mailaddress'];
                   header("Location: Main.php"); // メイン画面へ遷移
                   exit(); // 処理終了
               } else {
                   // 認証失敗
                   $errorMessage = 'ユーザーIDあるいはパスワードに誤りがあります。';
               }
           } else {
               // 4. 認証成功なら、セッションIDを新規に発行する
               // 該当データなし
               $errorMessage = 'ユーザーIDあるいはパスワードに誤りがあります。';
           }
       } catch (PDOException $e) {
           $errorMessage = 'データベースエラー';
           //$errorMessage = $sql;
           // $e->getMessage() でエラー内容を参照可能(デバック時のみ表示)
           // echo $e->getMessage();
       }
   }
}
?>
<!doctype html>
<html>
<head>
   <meta charset="UTF-8">
   <title>ログイン</title>
</head>
<body>
<h1>ログイン画面</h1>
<!-- $_SERVER['PHP_SELF']はXSSの危険性があるので、actionは空にしておく -->
<!-- <form id="loginForm" name="loginForm" action="<?php print($_SERVER['PHP_SELF']) ?>" method="POST"> -->
<form id="loginForm" name="loginForm" action="" method="POST">
   <fieldset>
       <legend>ログインフォーム</legend>
       <div><font color="#ff0000"><?php echo $errorMessage ?></font></div>
       <label for="userid">ユーザーID</label><input type="text" id="userid" name="userid" placeholder="ユーザーIDを入力"
                                                value="<?php if (!empty($_POST["userid"])) {
                                                    echo htmlspecialchars($_POST["userid"], ENT_QUOTES);
                                                } ?>">
       <label for="mailaddress">ユーザーID</label><input type="text" id="mailaddress" name="mailaddress"
                                                     placeholder="ユーザーIDを入力"
                                                     value="<?php if (!empty($_POST["userid"])) {
                                                         echo htmlspecialchars($_POST["userid"], ENT_QUOTES);
                                                     } ?>">
       <br>
       <label for="password">パスワード</label><input type="password" id="password" name="password" value=""
                                                 placeholder="パスワードを入力">
       <br>
       <input type="submit" id="login" name="login" value="ログイン">
   </fieldset>
</form>
<br>
<form action="SignUp.php">
   <fieldset>
       <legend>新規登録フォーム</legend>
       <input type="submit" value="新規登録">
   </fieldset>
</form>
</body>
</html>
```
ちなみに、メールアドレスでの登録ということは、新規登録のときに[filter_var関数](http://php.net/manual/ja/function.filter-var.php)などで**ユーザーが入力した文字列がメールアドレスの形式なのかチェックする**必要があると思います。質問者さんはこちらもリンクしているページの新規登録を参考にしていると思うので、メールアドレスのチェックを加えたコードを以下に書いておきます。
```PHP
<?php
session_start();
$db['host'] = "localhost"; // DBサーバのURL
$db['user'] = "root"; // ユーザー名
$db['pass'] = "pass"; // ユーザー名のパスワード
$db['dbname'] = "loginManagement"; // データベース名
// エラーメッセージ、登録完了メッセージの初期化
$errorMessage = "";
$SignUpMessage = "";
// ログインボタンが押された場合
if (isset($_POST["signUp"])) {
   // 1. ユーザIDの入力チェック
   if (empty($_POST["mailaddress"])) { // 値が空のとき
       $errorMessage = 'mailaddressが未入力です。';
   } else if (empty($_POST["password"])) {
       $errorMessage = 'パスワードが未入力です。';
   } else if (empty($_POST["password2"])) {
       $errorMessage = 'パスワードが未入力です。';
   }
   if (!empty($_POST["mailaddress"]) && !empty($_POST["password"]) && !empty($_POST["password2"]) && $_POST["password"] == $_POST["password2"] && filter_var($_POST['mailaddress'], FILTER_VALIDATE_EMAIL)) {
       // 入力したユーザIDとパスワードを格納
       $mailaddress = $_POST["mailaddress"];
       $password = $_POST["password"];
       // 2. ユーザIDとパスワードが入力されていたら認証する
       $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']);
       // 3. エラー処理
       try {
           $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
           $stmt = $pdo->prepare("INSERT INTO userData(mailaddress, password) VALUES (?, ?)");
           $stmt->execute(array($mailaddress, password_hash($password, PASSWORD_DEFAULT))); // パスワードのハッシュ化を行う(今回は文字列のみなのでbindValue(変数の内容が変わらない)を使用せず、直接excuteに渡しても問題ない)
           $userid = $pdo->lastinsertid(); // 登録した(DB側でauto_incrementした)IDを$useridに入れる
           $SignUpMessage = '登録が完了しました。あなたの登録ユーザIDは ' . $userid . ' です。パスワードは ' . $password . ' です。'; // ログイン時に使用するIDとパスワード
       } catch (PDOException $e) {
           $errorMessage = 'データベースエラー';
           // $e->getMessage() でエラー内容を参照可能(デバック時のみ表示)
           // echo $e->getMessage();
       }
   } elseif ($_POST["password"] != $_POST["password2"]) {
       $errorMessage = 'パスワードに誤りがあります。';
   } elseif (filter_var($_POST['mailaddress'], FILTER_VALIDATE_EMAIL) == false) {
       $errorMessage = 'メールアドレスの書式が間違っています。';
   }
}
?>
<!doctype html>
<html>
<head>
   <meta charset="UTF-8">
   <title>新規登録</title>
</head>
<body>
<h1>新規登録画面</h1>
<!-- $_SERVER['PHP_SELF']はXSSの危険性があるので、actionは空にしておく -->
<!-- <form id="loginForm" name="loginForm" action="<?php print($_SERVER['PHP_SELF']) ?>" method="POST"> -->
<form id="loginForm" name="loginForm" action="" method="POST">
   <fieldset>
       <legend>新規登録フォーム</legend>
       <div><font color="#ff0000"><?php echo $errorMessage ?></font></div>
       <div><font color="#0000ff"><?php echo $SignUpMessage ?></font></div>
       <label for="mailaddress">ユーザー名</label><input type="text" id="mailaddress" name="mailaddress"
                                                    placeholder="ユーザー名を入力"
                                                    value="<?php if (!empty($_POST["mailaddress"])) {
                                                        echo htmlspecialchars($_POST["mailaddress"], ENT_QUOTES);
                                                    } ?>">
       <br>
       <label for="password">パスワード</label><input type="password" id="password" name="password" value=""
                                                 placeholder="パスワードを入力">
       <br>
       <label for="password2">パスワード(確認用)</label><input type="password" id="password2" name="password2" value=""
                                                       placeholder="再度パスワードを入力">
       <br>
       <input type="submit" id="signUp" name="signUp" value="新規登録">
   </fieldset>
</form>
<br>
<form action="Login.php">
   <input type="submit" value="戻る">
</form>
</body>
</html>
```

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る