ログイン処理

「users」テーブルをレコード検索して、Emailとパスワードでログイン認証を作成します。

ファイル構成

php_sns/
├── lib/
│        └── Model.php
├── regist/
│        ├── add.php
│        ├── complete.php
│        ├── confirm.php
│        ├── index.php
│        └── input.php
├── login/
│        ├── auth.php
│        └── index.php
├── app.php
└── env.php

トップページ

トップページ「login/index.php」にアクセスしたら、ログイン画面「login/input.php」にリダイレクトするように修正します。

login/index.php
<?php
header('Location: input.php');

ログイン画面

ログイン画面「login/input.php」を作成し、ログインフォームを追加します。

login/input.php
<?php
require_once "../app.php";
?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= SITE_TITLE ?></title>
    <base href="<?= BASE_URL ?>">
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
    <main id="regist" class="flex justify-center">
        <div class="w-1/2 mt-3 p-5">
            <h2 class="text-2xl mb-3 font-normal text-center">Sign in</h2>
            <form action="login/auth.php" method="post">
                <div class="relative mb-4">
                    <div class="relative mb-4">
                        <input type="email" name="email" id="email" class="block
                        px-2.5 pb-2.5 pt-6 mb-3
                        w-full rounded-lg
                        text-sm 
                        text-gray-900 
                        ring-1 ring-gray-300 
                        focus:outline-none 
                        focus:ring-1 
                        focus:ring-blue-600 
                        peer" placeholder=" " required>
                        <label for="email" class="absolute 
                        text-sm text-gray-400 
                        duration-300 
                        transform -translate-y-4 scale-75 
                        top-4 
                        origin-[0] start-2.5 
                        peer-focus:px-0
                        peer-focus:text-blue-600 
                        peer-focus:dark:text-blue-500 
                        peer-placeholder-shown:scale-100 
                        peer-placeholder-shown:translate-y-0 
                        peer-focus:scale-75 
                        peer-focus:-translate-y-4">
                            Email
                        </label>
                    </div>
                    <div class="relative mb-4">
                        <input type="password" name="password" id="password" class="block
                        px-2.5 pb-2.5 pt-6 mb-3 
                        w-full rounded-lg
                        text-sm 
                        text-gray-900 
                        ring-1 ring-gray-300 
                        focus:outline-none 
                        focus:ring-1 
                        focus:ring-blue-600 
                        peer" placeholder=" " required>
                        <label for="password" class="absolute 
                        text-sm text-gray-400 
                        duration-300 
                        transform -translate-y-4 scale-75 
                        top-4 
                        origin-[0] start-2.5 
                        peer-focus:px-0
                        peer-focus:text-blue-600 
                        peer-focus:dark:text-blue-500 
                        peer-placeholder-shown:scale-100 
                        peer-placeholder-shown:translate-y-0 
                        peer-focus:scale-75 
                        peer-focus:-translate-y-4">
                            パスワード
                        </label>
                    </div>


                    <div>
                        <button id="submit_button" class="w-full
                        mb-2 py-2 px-4 bg-sky-500 
                        hover:bg-sky-700 
                        text-white 
                        rounded-lg
                        disabled:bg-blue-300">
                            Sign in
                        </button>
                    </div>
                </div>
            </form>
        </div>
    </main>
</body>

</html>

認証処理

Emailでユーザ検索し、ユーザが見つかったらパスワードのハッシュ検証をします。

データ取得

POSTデータからEmailとパスワードを取得します。

login/input.php
// 設定ファイル「app.php」読み込み
require_once '../app.php';

// POSTリクエストでなければ何も表示しない
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit;
}

// POSTデータ取得
$posts = $_POST;
$email = $posts['email'];
$password = $posts['password'];

認証メソッド

認証メソッドauth() を追加します。引数は、PDOオブジェクト、Email、パスワードとします。

login/input.php
function auth($pdo, $email, $password)
{

}

Email検索

Email検索のデータ取得します。

login/input.php
function auth($pdo, $email, $password)
{
    $sql = "SELECT * FROM users WHERE email = :email";
    $stmt = $pdo->prepare($sql);
    $stmt->execute(['email' => $email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
}

パスワードハッシュ検証

ユーザが検索されたら、パスワードハッシュの検証をします。

login/input.php
function auth($pdo, $email, $password)
{
    $sql = "SELECT * FROM users WHERE email = :email";
    $stmt = $pdo->prepare($sql);
    $stmt->execute(['email' => $email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($user && password_verify($password, $user['password'])) {
        return $user;
    }
}

認証実行

auth() を実行してユーザ認証を確認します。

login/input.php
$user = auth($pdo, $email, $password);
var_dump($user);

ログイン確認

Email とパスワードでログイン認証してみましょう。パスワードはすべて「password」にしています。

結果

Email とパスワードが一致してユーザ認証できました。

array(7) {
  ["id"]=>
  int(2)
  ["name"]=>
  string(13) "渡辺 直人"
  ["email"]=>
  string(25) "[email protected]"
...

セッション処理

認証が成功したらユーザ情報をセッションに保存します。

login/input.php
<?php
...

$posts = $_POST;
$email = $posts['email'];
$password = $posts['password'];

// ユーザ認証
if ($user = auth($model->pdo, $email, $password)) {
    // セッションにユーザデータを登録
    $_SESSION[APP_KEY]['user'] = $user;
} else {

}
...

リダイレクト

認証が成功した場合は「user/」に、失敗した場合は「login/」にリダイレクトします。

login/input.php
<?php
require_once '../app.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit;
}

$model = new Model();

$posts = $_POST;
$email = $posts['email'];
$password = $posts['password'];

// ユーザ認証
if ($user = auth($model->pdo, $email, $password)) {
    // セッションにユーザを登録
    $_SESSION[APP_KEY]['user'] = $user;

    //ログイン成功の場合、user/ にリダイレクト
    header('Location: ../user/');
} else {
    //ログイン失敗の場合、login/input.php にリダイレクト
    header('Location: input.php');
}

// ユーザ認証メソッド
function auth($pdo, $email, $password)
{
    $sql = "SELECT * FROM users WHERE email = :email";
    $stmt = $pdo->prepare($sql);
    $stmt->execute(['email' => $email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($user && password_verify($password, $user['password'])) {
        return $user;
    }
}

認証ページ

ユーザセッションをチェックして、ログイン認証が必要なページのアクセスを制御します。

ユーザホーム作成

「user/index.php」を作成します。

user/index.php
<?php
require_once '../app.php';
?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= SITE_TITLE ?></title>
    <base href="<?= BASE_URL ?>">
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>

</body>

</html>

認証チェック

セッションにユーザ情報があるかチェックします。

user/index.php
<?php
require_once '../app.php';

if (empty($_SESSION[APP_KEY]['user'])) {
    header('Location: ../login/');
} else {
    $user = $_SESSION[APP_KEY]['user'];
}

ユーザ情報表示

セッションで取得したユーザ情報が表示されるか確認してみましょう。

user/index.php
<?php 
require_once '../app.php';

if (empty($_SESSION[APP_KEY]['user'])) {
    header('Location: ../login/');
} else {
    $user = $_SESSION[APP_KEY]['user'];
}
?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= SITE_TITLE ?></title>
    <base href="<?= BASE_URL ?>">
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
<main class="flex justify-center">
        <div class="w-full mt-3 p-5">
            <h2 class="text-2xl mb-3 font-normal text-center">ユーザホーム</h2>
            <div class="mb-4">
                <p class="text-center text-gray-700 text-md"><?= $user['name'] ?>さん</p>
            </div>
            <div class="mb-4 flex justify-center">
                <a href="user/logout.php" class="w-full
                        mx-1 mb-4 py-2 px-4
                        text-gray-500 
                        text-center
                        bg-gray-100
                        hover:bg-gray-200 
                        rounded">
                    ログアウト
                </a>
            </div>
        </div>
    </main>
</body>

</html>

ログアウト

ログアウト処理

「user/logout.php」でログアウト処理をします。

<?php
require_once "../app.php";

if (isset($_SESSION[APP_KEY]['user'])) {
    unset($_SESSION[APP_KEY]['user']);
}

header('Location: ../login/');

ログアウトの確認

ログアウトできるか確認します。また、ログアウト後は「user/index.php」にアクセスできないことを確認しましょう。

PHP + MySQL Webサーバプログラミング