はじめに
前回の記事でログイン機能を実装しました。
https://qiita.com/N46_myHearter/items/ae4f776790c4c4666a66
この記事では、ログインする際に使用するアカウントをデータベースに登録する機能を実装してみたいと思います。
###基本的な流れ
- 登録するユーザ情報(ID、パスワード、ユーザ名)を入力します。
- 入力値チェックを行う。
- ユーザ情報をDBに登録する。
簡易なので...笑笑
データベース
今回は、MySQLを使用しています。
データ項目は、ID、パスワード、ユーザ名の3つのみで構成しています。
プライマリーキーにIDを指定しています。
パスワードは、ハッシュ化で暗号化。(調べた時にハッシュ化だと簡単に出来たから笑笑)
該当ソースコード
1. register.php
アカウントを登録するための入力画面です。
入力項目は、ID、名前、パスワード(確認のため2回入力)です。
入力項目すべて入力されているか、2回入力したパスワードが一致しているか、
パスワードの強度は大丈夫か(強度が弱いと警告)を確認して、アカウント登録確認画面に遷移します。
パスワード強度チェックは以下のHPにあるオープンソースであるpasswordchecker.jsを利用しています。
出典 https://www.websec-room.com/passswordchecker
<?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に既に存在していないかをチェックします。
既に登録されていた場合はエラーを返します。
<?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に入力したユーザ情報を格納します。
その時、パスワードはハッシュ化で暗号化します。
<?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等をまとめてインストールでき、インストールも簡単なので)
おわりに
抜けている箇所がありましたら、コメント欄で教えていただくとありがたいです。