PHP初心者です。
PHPの勉強がてら、会員制のページを作成してます。
新規会員登録機能は実装できていますが、
ログイン機能の実装がうまくいきません。
やりたいことを実現するにはどのように記述すればよいか
ご教授頂けませんでしょうか。
やりたいことは以下です。
<ToBe>
・DBに登録されているメールアドレス・パスワードでのみログイン可
・メールアドレス、パスワードのいずれかが空欄のときは
エラーメッセージを表示したい。
・ログイン後はメインページに遷移。
<AsIs>
・常にエラーメッセージが表示されている。
・登録済みのユーザでログインできない
以下、ソースです。
index.html (17/3/1 追記 ver1.1)
<?php
require('dbconnect.php');
session_start();
if(isset($_POST)){
if(!empty($_POST)){ //ログインの処理
if($_POST['mail'] != '' && $_POST['pass'] != ''){
$sql = sprintf('SELECT * FROM users WHERE mail="%s" AND pass="%s"',
mysqli_real_escape_string($db, $_POST['mail']),
mysqli_real_escape_string($db, sha1($_POST['pass']))
);
$record = mysqli_query($db, $sql) or die(mysqli_error($db));
$result = mysqli_fetch_assoc($record);
if(!empty($result)){ //ログイン成功
header('Location: main.php');
exit();
}else{
$error['login'] = 'failed';
}
}else{
$error['login'] = 'blank';
}
}
}
ini_set('display_errors', 1);
error_reporting(E_ALL);
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body bgcolor="#FAFC7B">
<h2>Login</h2>
<img src="nekos.jpg">
<form action="" method="post">
<dl>
<dt>メールアドレス</dt>
<dd><input type="text" name="mail" size="35" maxlength="255"> </dd>
<dt>パスワード</dt>
<dd><input type="password" name="pass" size="35" maxlength="255"></dd>
</dl>
<input type="submit" value="ログイン">
<?php var_dump($error['login']); ?>
<?php if(!empty($error['login']) && $error['login'] == 'blank'): ?>
<p><font color="red">* メールアドレスまたはパスワードをご記入ください</font></p>
<?php endif; ?>
<?php if(!empty($error['login']) && $error['login'] == 'failed'): ?>
<p><font color="red">* ログインに失敗しました。正しくご記入ください。</font></p>
<?php endif; ?>
</form>
<HR>
<a href="join/register.php">新規登録</a>
<a href="lookingforpass.php">パスワード照会</a>
<a href="contact.html">お問い合わせ</a>
</body>
</html>
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+3
開発時は必ず、下に示したコードのように、
ini_set('display_errors', 1);
error_reporting(E_ALL);
を記述し、 エラーメッセージを表示してください 。
質問する際には、表示されたエラーを記述するようにしましょう。
もっとも、表示されたエラーには、「なぜうまくいかないか」の理由が書かれているものですから、質問を建てる前に、自己解決できる場合がほとんどです。
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
require('dbconnect.php');
やっつけサンプル
SQL
CREATE TABLE `Users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(64) DEFAULT NULL,
`password` varchar(256) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- password = 'password'
INSERT INTO `Users` (`id`, `email`, `password`)
VALUES
(1,'user@example.com','$2y$10$OqyHPnhhs7nFZGrB/P7wDuN1sZ7olqyc8r3bUTXIKRqg00eJRu/W2');
index.php
<?php
/**
* index.php
*/
ini_set('display_errors', true);
error_reporting(E_ALL);
session_start();
define('DSN', 'mysql:host=localhost;dbname=sample;charset=utf8');
define('USERNAME', 'root');
define('PASSWORD', 'password');
/**
* htmlspecialchars
*/
function h($string)
{
return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}
/**
* SELECT
*/
function select($sql, $params = [])
{
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
$objPdo = new PDO(DSN, USERNAME, PASSWORD, $options);
$stmt = $objPdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll();
}
/**
* ログイン
*/
function login()
{
if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
return;
}
$email = filter_input(INPUT_POST, 'email');
$password = filter_input(INPUT_POST, 'password');
if (empty($email) || empty($password)) {
throw new Exception('メールアドレスおよびパスワードは入力必須です。');
}
$sql = 'SELECT * FROM `Users` WHERE `email` = :email ';
$params = [];
$params['email'] = $email;
$rows = select($sql, $params);
$user = reset($rows);
if (count($rows) === 0 || !password_verify($password, $user['password'])) {
throw new Exception('メールアドレスおよびパスワードが間違っています。');
}
session_regenerate_id(true);
$_SESSION['login_user'] = $user;
return true;
}
try {
if (login()) {
header('Location: top.php');
}
} catch (Exception $ex) {
$err = $ex->getMessage();
}
?>
<!DOCTYPE html>
<html lang="en">
<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>Signin Template for Bootstrap</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #eee;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>
</head>
<body>
<div class="container">
<?php if (isset($err)) : ?>
<div class="alert alert-danger">
<p>
<?= h($err); ?>
</p>
</div>
<?php endif; ?>
<form class="form-signin" method="post">
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">
Email address
</label>
<input type="email" name="email" id="inputEmail" class="form-control" placeholder="Email address" autofocus>
<label for="inputPassword" class="sr-only">
Password
</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password">
<button class="btn btn-lg btn-primary btn-block" type="submit">
Sign in
</button>
</form>
</div> <!-- /container -->
</body>
</html>
top.php
<?php
/**
* top.php
*/
ini_set('display_errors', true);
error_reporting(E_ALL);
session_start();
/**
* htmlspecialchars
*/
function h($string)
{
return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}
/**
* check_login
*/
function check_login()
{
$res = (isset($_SESSION['login_user']) && $_SESSION['login_user'] != NULL);
if (!$res) {
header('Location: index.php');
}
}
check_login();
?>
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<?= h($_SESSION['login_user']['email']); ?>
</body>
</html>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
まずはテンプレですが…質問文のコードはそれぞれコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。 次にカッコが抜けていたりする箇所が多かったです。それが動作が想定と異なる原因になります。個人的にはIDEの利用をお勧めします。私がつかっているのはNetbeansですが、それ以外にも無料のIDEがあるので使ってみてください。少なくとも、文法エラーは一目瞭然でわかりますので…
で、実際に拝見したコードを軽く直してみました。とりあえず、ログインの為のDB読込はできると思いますよ。
<?php
require('dbconnect.php');
session_start();
if(isset($_POST)){
if(!empty($_POST)){ //ログインの処理
if($_POST['mail'] != '' && $_POST['pass'] != ''){
$sql = sprintf('SELECT * FROM users WHERE mail="%s" AND pass="%s"',
mysqli_real_escape_string($db, $_POST['mail']),
mysqli_real_escape_string($db, sha1($_POST['pass']))
);
$record = mysqli_query($db, $sql) or die(mysqli_error($db));
$result = mysqli_fetch_assoc($record);
if(!empty($result)){ //ログイン成功
header('Location: main.php');
exit();
}else{
$error['login'] = 'failed';
}
}else{
$error['login'] = 'blank';
}
}else{
echo '<p>NOSET!!!!</p>';
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ログインページ</title>
</head>
<body bgcolor="#FAFC7B">
<h2>ログインページ</h2>
<img src="nekos.jpg">
<form action="" method="post">
<dl>
<dt>メールアドレス</dt>
<dd><input type="text" name="mail" size="35" maxlength="255"> </dd>
<dt>パスワード</dt>
<dd><input type="password" name="pass" size="35" maxlength="255"></dd>
</dl>
<input type="submit" value="ログイン">
<?php if(!empty($error['login']) && $error['login'] == 'blank'): ?>
<p><font color="red">* メールアドレスまたはパスワードをご記入ください</font></p>
<?php endif; ?>
<?php if(!empty($error['login']) && $error['login'] == 'failed'): ?>
<p><font color="red">* ログインに失敗しました。正しくご記入ください。</font></p>
<?php endif; ?>
</form>
<HR>
<a href="join/register.php">新規登録</a>
<a href="lookingforpass.php">パスワード照会</a>
<a href="contact.html">お問い合わせ</a>
</body>
</html>
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
質問とは全く関係ない部分ですが、
pass=sha1($_POST['pass'])
暗号強度はほぼゼロなので使ってはいけません。
例:passが'5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8'ならパスワードは'password'と判る
× 固定値SALTを使う
http://qiita.com/shunsuke_takahashi/items/fcbe1e08aa94b208c14a
△ 個別SALTを使う
http://qiita.com/ms2sato/items/6005eea50def287090d0
○ password_hashを使う
// パスワード登録時
$sql = 'INSERT INTO users (mail, pass) VALUES (?, ?)';
$stmt = mysqli_prepare($db, $sql);
mysqli_stmt_bind_param($stmt, 'ss', $_REQUEST['mail'], password_hash($_REQUEST['pass'], PASSWORD_DEFAULT));
mysqli_stmt_execute($stmt);
// パスワード照合時
$sql = 'SELECT * FROM users WHERE mail = ?';
$stmt = mysqli_prepare($db, $sql);
mysqli_stmt_bind_param($stmt, 's', $_REQUEST['mail']);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $user);
mysqli_stmt_fetch($stmt);
if(password_verify($_REQUEST['pass'], $user['pass'])){
// ログイン成功
}
あと手続き型mysqliはわかりにくいので、mysqliクラスにするかPDOをお勧めします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.22%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
kei344
2017/03/01 14:04
質問文のコードはそれぞれコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
kei344
2017/03/04 14:46
まだ質問が「受付中」になっていますが、いったん「解決済」にされてはいかがでしょうか。また、解決されていないなら状況を追記ください。
shar0430
2017/03/05 11:44
皆さん、ご丁寧に御回答頂きありがとうございます。ベストアンサーは悩みましたが、解決のきっかけとなったKosuke_shibuyaに決めさせて頂きました。ありがとうございました。