1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[PHP] 簡易ログインアカウント登録機能を実装してみた

Last updated at Posted at 2020-08-12

はじめに

前回の記事でログイン機能を実装しました。
https://qiita.com/N46_myHearter/items/ae4f776790c4c4666a66

この記事では、ログインする際に使用するアカウントをデータベースに登録する機能を実装してみたいと思います。

###基本的な流れ

  1. 登録するユーザ情報(ID、パスワード、ユーザ名)を入力します。
  2. 入力値チェックを行う。
  3. ユーザ情報をDBに登録する。

簡易なので...笑笑

データベース

今回は、MySQLを使用しています。
データ項目は、IDパスワードユーザ名の3つのみで構成しています。
プライマリーキーにIDを指定しています。
パスワードは、ハッシュ化で暗号化。(調べた時にハッシュ化だと簡単に出来たから笑笑)

該当ソースコード

1. register.php

アカウントを登録するための入力画面です。
入力項目は、ID、名前、パスワード(確認のため2回入力)です。
入力項目すべて入力されているか、2回入力したパスワードが一致しているか、
パスワードの強度は大丈夫か(強度が弱いと警告)を確認して、アカウント登録確認画面に遷移します。

パスワード強度チェックは以下のHPにあるオープンソースであるpasswordchecker.jsを利用しています。
出典 https://www.websec-room.com/passswordchecker

アカウント登録画面(register.php)
<?php
  session_start();
  header("Content-type: text/html; charset=utf-8");
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <link rel="stylesheet" type="text/css" href="style1.css"> 
  <meta charset="UTF-8">
  <script src="passwordchecker.js" type="text/javascript"></script>
  <script src="common.js" type="text/javascript"></script>
  <script type="text/javascript">
  
  /*
  * 登録前チェック  
  */
  function conrimMessage() {
    var id = document.getElementById("id").value;
    var name = document.getElementById("name").value;
    var pass = document.getElementById("password").value;
    var conf = document.getElementById("confirm_password").value;

    //必須チェック
    if((id == "") || (name == "") || (pass == "") || (conf == "")) {
      alert("必須項目が入力されていません。");
      return false;
    }

    //パスワードチェック
    if (pass != conf) {
      alert("パスワードが一致していません。");
      return false;
    }

    if (passwordLevel < 3) {
      return confirm("パスワード強度が弱いですがよいですか?");
    }

    return true;
    }

  </script>
</head>

<div class="form-wrapper">
  <h1>アカウント登録</h1>
  
  <?php
    if (isset($_SESSION["error_status"])) {
      if ($_SESSION["error_status"] == 1) {
        echo "<h2 style='color:red;'>入力内容に誤りがあります。</h2>";
      }
      if ($_SESSION["error_status"] == 2) {
        echo "<h2 style='color:red;'>IDは既に登録されています。</h2>";
      }
      if ($_SESSION["error_status"] == 3) {
        echo "<h2 style='color:red;'>タイムアウトか不正な URL です。</h2>";
      }
      if ($_SESSION["error_status"] == 4) {
        echo "<h2 style='color:red;'>登録に失敗しました。</h2>";
      }
      if ($_SESSION["error_status"] == 5) {
        echo "<h2 style='color:red;'>パスワードは既に登録されています。</h2>";
      }
    }
  ?>

  <form action="register_check.php" method="post" onsubmit="return conrimMessage();">
  <div class="form-item">
    <label for="ID"></label>
    <input type="text" name="id" id="id" required="required" placeholder="ID">
  </div>
  <div class="form-item">
    <label for="NAME"></label>
    <input type="text" name="name" id="name" required="required" placeholder="名前">
  </div>
  <div class="form-item">
    <label for="password"></label>
    <input type="password" name="password" required="required" placeholder="パスワード">
  </div>
  <div class="form-item">
    <label for="password"></label>
    <input type="password" name="confirm_password" id="confirm_password" required="required" placeholder="パスワード(確認)">
  </div>

  <div class="button-panel">
    <input type="submit" class="button" title="登録" value="登録">
  </div>
  </form>

  <div class="form-footer">
    <p><a href="/login.php">戻る</a></p>
  </div>
</div>
</html>

2. register_check.php

本当にアカウント登録していいのか再度確認する画面です。
また、入力したアカウント情報がDBに既に存在していないかをチェックします。
既に登録されていた場合はエラーを返します。

アカウント登録確認画面(register_check.php)
<?php
  require_once("function.php");
  session_start();
  header("Content-type: text/html; charset=utf-8");  
  
  $_SESSION['token']  = get_csrf_token();

  $id = $_POST['id'];
  $password = $_POST['password'];
  $name = $_POST['name'];
  $confirm_password = $_POST['confirm_password'];

  if ($password != $confirm_password) {
    //パスワード不一致 
    $_SESSION["error_status"] = 1;
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: register.php");
    exit();
  }  

  //IDチェック

  //DB接続
  try {
    /*dbname: test
      host: localhost (DBをローカル環境に置いている)
      username: root
      password: '' (未設定)
    */
    $pdo = new PDO('mysql:dbname=test;host=localhost;charset=utf8mb4', 'root', '',
      [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
      ]
      );

    $stmt = $pdo->query('SELECT id, password FROM USER');

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
      $db_id = $row["id"];
      $db_password = $row["password"];

    //既にIDが登録されていた
    if ($db_id == $id) {
      $_SESSION["error_status"] = 2;
      header("HTTP/1.1 301 Moved Permanently");
      header("Location: register.php");
      exit();
    } 

    //エラー情報リセット
    $_SESSION["error_status"] = 0;
    }
    } catch (PDOException $e) {
      exit('データベース接続失敗。'.$e->getMessage());
    }

?>

<!DOCTYPE html>
<head>
  <link rel="stylesheet" type="text/css" href="style1.css">
  <meta charset="utf-8">
</head>

<html lang="ja">
<div class="form-wrapper">
  <h1>登録確認</h1>
  <h2>アカウント登録しますか?</h2>
  <form action="register_submit.php" method="post">
    <table border="0">
    
      <input type="hidden" name="id" value="<?php echo htmlspecialchars($id  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="name" value="<?php echo htmlspecialchars($name  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="password" value="<?php echo htmlspecialchars($password  , ENT_QUOTES, "UTF-8") ?>">
      <input type="hidden" name="token" value="<?php echo htmlspecialchars($_SESSION['token']  , ENT_QUOTES, "UTF-8") ?>">

      <div class="button-panel">
        <input type="submit" class="button" title="登録" value="登録">
      </div>
    </form>

    <div class="form-footer">
        <p><a href="/register.php">戻る</a></p>
    </div>
</div>
</html>

3. register_submit.php

実際にアカウント登録をして、登録完了を知らせる画面です。
DBに入力したユーザ情報を格納します。
その時、パスワードはハッシュ化で暗号化します。

アカウント登録完了画面(register_submit.php)
<?php
  require_once("function.php");
  session_start();
  header("Content-type: text/html; charset=utf-8");

  //CSRF チェック
  if ($_SESSION['token'] != $_POST['token']) {
      $_SESSION = array();
      session_destroy();
      session_start();

    $_SESSION["error_status"] = 2;
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: login.php");
    exit();
  } 

  //エラー情報のリセット
  $_SESSION["error_status"] = 0;

  $id = $_POST['id'];
  $password = $_POST['password'];
  $name = $_POST['name'];

  // ハッシュを作る
  $hash = password_hash($password, PASSWORD_BCRYPT);

  //DB接続
  try {
    /*dbname: test
      host: localhost (DBをローカル環境に置いている)
      username: root
      password: '' (未設定)
    */
    $pdo = new PDO('mysql:dbname=test;host=localhost;charset=utf8mb4', 'root', '', 
    [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
    );

    //パラメーターの型を指定
    $stmt = $pdo->prepare('INSERT INTO USER (ID, NAME, PASSWORD) VALUES (:id, :name, :password)'); 
    $stmt->bindParam(':id', $id, PDO::PARAM_STR);
    $stmt->bindParam(':name', $name, PDO::PARAM_STR);
    $stmt->bindParam(':password', $hash, PDO::PARAM_STR);

    $stmt->execute();
  } catch (PDOException $e) {
    exit('データベース接続失敗。'.$e->getMessage());
  }
  
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <link rel="stylesheet" type="text/css" href="style1.css">
  <meta charset="utf-8">
</head>

<<div class="form-wrapper">
  <h1>アカウント登録完了</h1>
  アカウント登録が終了しました。<br>
  ログイン画面からログインしてください。<br><br>

	<div class="form-footer">
    <p><a href="/login.php">ログイン画面に戻る</a></p>
  </div>
</div>
</html>

4. function.php

以下の前回の記事に掲載済み。
https://qiita.com/N46_myHearter/items/ae4f776790c4c4666a66

環境

windows10 64bit
実行環境: xampp (mysql、php、apache等をまとめてインストールでき、インストールも簡単なので)

おわりに

抜けている箇所がありましたら、コメント欄で教えていただくとありがたいです。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?