PHPまとめ④:ログインの仕組みを作る
今回は以下のファイルを作成する。
login.php
- メールアドレスとパスワードを確認し、ログインする仕組みを作る
login_view.php
- 会員登録後に飛んでくる画面であり、ログインボタンを備える
db_helper.php
- 入力されたメールアドレスとパスワードがデータベースのものと一致するかを調べる関数を作る
まずはコントローラであるlogin.phpを作成する。実はsignup.phpを一部流用できる。
<?php
//必要ファイル読み込み
require_once('config.php');
require_once('./helpers/db_helper.php');
require_once('./helpers/extra_helper.php');session_start();
//既にログイン済みだった場合、member.phpへリダイレクト
if($_SERVER['REQUEST_METHOD']==='POST'){
//$name=get_post('name');
$email=get_post('email');
$password=get_post('password');
$dbh=get_db_connection(); //データベース接続
$errs=array();//バリデーション
// if(!check_words($name,50)){
// $errs['name']='お名前欄は必ず50文字以内で入力してください(必須項目)。';
// }
if(!filter_var($email,FILTER_VARIDATE_EMAIL)){
$errs['email']='メールアドレスの形式が正しくありません。';
}elseif(email_exists($dbh,$email)){
$errs['email']='このメールアドレスは既に登録されています。';
}elseif(!check_words($email,100)){
$errs['email']='メールアドレスは100文字以内で入力してください(必須項目)。';
}
if(!check_words($password,50)){
$errs['password']='パスワードは50文字以内で入力してください(必須項目)。';
}//エラーがなければデータ挿入
// if(empty($errs)){
// if(insert_member_data($dbh,$name,$email,$password)){
// header('Location:'.SITE_URL.'login.php');
// exit();
// }
// $errs['password']='登録に失敗しました。';
// }//メールアドレスとパスワードが一致するか検証
//ログインする
}include_once('./views/login_view.php'); //ビューファイル読み込み
コメントアウトしてある箇所はsignup.phpにはあったが今回は使わない箇所(次からは消しておく)。これから制作していく箇所にコメントを入れている。
ログイン用のビューファイルも作成しておく。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ログイン画面</title>
</head>
<body>
<h1>ログイン</h1>
<form action="" method="POST">
<p>メールアドレス:<input type="text" name="email"><?php echo html_escape($errs['email']); ?></p>
<p>パスワード:<input type="password" name="password"><?php echo html_escape($errs['password']); ?></p>
<p><input type="submit" value="ログイン"></p>
<p><a href="index.php">新規登録</a>
</form>
</body>
</html>
メールアドレスとパスワードだけでログインするシンプルな画面になる。
次に、db_helper.phpに以下の関数を追加する。メールアドレスとパスワードが一致した場合、会員データを配列で返す。
function select_member($dbh,$email,$password){
$sql="select * from members where email=:email limit 1";
$stmt=$dbh->prepare($sql);
$stmt->bindvalue(':email',$email,PDO::PARAM_STR);
$stmt->execute();
if($stmt->rowCount()>0){
$data=$stmt->fetch(PDO::FETCH_ASSOC):
if(password_verify($password,$data['password'])){
return $data; //会員データを返す
}else{
return false;
}
}else{
return false;
}
}
この関数では、まずメールアドレスの一致する会員データを引き出すSQLを作る。同じメールアドレスは存在しないようになっているが、「LIMIT 1」で1件だけ取得することを明記する。password_verify()を使って入力されたパスワードとデータベースに登録されたパスワードが一致するかを調べる。第1引数は入力値、第2引数はすでにハッシュ化されてデータベースに登録されていたパスワードとなる。一致したらtrueが返ってくる。
この関数をlogin.phpのバリデーションに加える。
//バリデーション
if(!filter_var($email,FILTER_VARIDATE_EMAIL)){
$errs['email']='メールアドレスの形式が正しくありません。';
}elseif(email_exists($dbh,$email)){
$errs['email']='このメールアドレスは既に登録されています。';
}elseif(!check_words($email,100)){
$errs['email']='メールアドレスは100文字以内で入力してください(必須項目)。';
}
if(!check_words($password,50)){
$errs['password']='パスワードは50文字以内で入力してください(必須項目)。';
}elseif(!$member=select_member($dbh,$email,$password)){
//メールアドレスとパスワードが一致するか検証
$errs['password']='メールアドレスとパスワードが正しくありません。'
}
これでパスワードの一致を確認できるようになった。
ログインに関わる仕組みを作る。バリデーション後のログインと、ログインしていた場合のリダイレクトである。login.phpに以下のコードを追加。
<?php
//必要ファイル読み込み
require_once('config.php');
require_once('./helpers/db_helper.php');
require_once('./helpers/extra_helper.php');session_start();
//既にログイン済みだった場合、member.phpへリダイレクト
if(!empty($_SESSION['member'])){
header('Location:'.SITE_URL.'/member.php');
exit();
}
//バリデーション
//中略
//ログインする
if(empty($errs)){
session_regenerate_id(true);//セッションIDの変更
$_SESSION['member']=$member;//ログイン
header('Location:'.SITE_URL.'/member.php');//会員ページへリダイレクト
}
}include_once('./views/login_view.php'); //ビューファイル読み込み
バリデーション側について、session_regenerate_id(true)でセッションIDの切り替えを行う。セッションがスタートしてからログインするまでの間にセッションIDが盗まれていた場合を想定し、セッションIDはログインの直前に変更しなければならない。ログインの仕組みそのものは$_SESSION['member']=$memberだけで終わる。
これ以降、$_SESSION['member']が存在するかどうかを確かめることでログイン状態を確認するようになる。ログインが終わったら会員ページへリダイレクトする。ログインが済んだ後にログインページに行くのもおかしな挙動となるので、session_start()直後にログイン済みのクライアントは会員ページへリダイレクトさせる。empty()を使って$_SESSION['member']が空であるかどうかを調べる。
以上でログインの仕組みは完成となる。