Skip to content

Instantly share code, notes, and snippets.

@kobitoDevelopment
Last active March 30, 2025 03:41
Show Gist options
  • Select an option

  • Save kobitoDevelopment/77aa3cb55c554ef15e849fc8a4eb568d to your computer and use it in GitHub Desktop.

Select an option

Save kobitoDevelopment/77aa3cb55c554ef15e849fc8a4eb568d to your computer and use it in GitHub Desktop.
<?php
define('DB_HOST', 'データベースのホスト名'); // データベースのホスト名
define('DB_USER', 'データベースのユーザー名'); // データベースのユーザー名
define('DB_PASS', 'データベースのパスワード'); // データベースのパスワード
define('DB_NAME', '使用するデータベース名'); // 使用するデータベース名
define('DB_CHARSET', 'データベースの文字コード'); // データベースの文字コード
?>
<?php
// DB接続情報
require_once '../config.php';
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$db_user = DB_USER;
$db_password = DB_PASS;
try {
// PDOインスタンスの作成
$dbh = new PDO($dsn, $db_user, $db_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// users テーブルの作成(パスワードリセットの際のURL用tokenと有効期限を設定)
$sql1 = "CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password_reset_token VARCHAR(255) DEFAULT NULL,
token_expires_at DATETIME DEFAULT NULL
)";
$dbh->exec($sql1);
echo "Tables created successfully.";
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<?php
session_start(); // セッションを開始
// CSRFトークンを生成(ランダムな文字列)
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>パスワード変更</title>
</head>
<body>
<section>
<h1>パスワード変更</h1>
<form action="sendmail.php" method="post">
<dl>
<div>
<dt>登録しているメールアドレス</dt>
<dd><input type="text" name="mail" required></dd>
</div>
</dl>
<!-- CSRFトークンを隠しフィールドとして送信 -->
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8'); ?>">
<button type="submit">パスワードリセットの案内を送信</button>
</form>
</section>
</body>
</html>
<?php
require_once 'config.php';
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$db_user = DB_USER;
$db_password = DB_PASS;
try {
$dbh = new PDO($dsn, $db_user, $db_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if (!isset($_GET['token'])) {
die("無効なアクセスです。");
}
$token = $_GET['token'];
$stmt = $dbh->prepare("SELECT id FROM users WHERE password_reset_token = ? AND token_expires_at > NOW()");
$stmt->execute([$token]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
die("このリンクは無効または有効期限が切れています。");
}
} catch (PDOException $e) {
die("Error: " . $e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>パスワードリセット</title>
</head>
<body>
<h1>パスワードをリセット</h1>
<form action="update-password.php" method="post">
<input type="hidden" name="token" value="<?= htmlspecialchars($token) ?>">
<label>新しいパスワード: <input type="password" name="password" required></label>
<button type="submit">更新</button>
</form>
</body>
</html>
<?php
session_start(); // セッションを開始
require_once 'config.php';
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$db_user = DB_USER;
$db_password = DB_PASS;
try {
$dbh = new PDO($dsn, $db_user, $db_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRFトークンの検証
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("不正なリクエストです。");
}
// トークンの使用後は削除(ワンタイムトークンとして機能させる)
unset($_SESSION['csrf_token']);
$email = $_POST['mail'];
$stmt = $dbh->prepare("SELECT id FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
// トークン生成
$token = bin2hex(random_bytes(32));
$expiry = date('Y-m-d H:i:s', strtotime('+1 hour')); // 1時間後に有効期限切れ
// DBに保存
$stmt = $dbh->prepare("UPDATE users SET password_reset_token = ?, token_expires_at = ? WHERE email = ?");
$stmt->execute([$token, $expiry, $email]);
// リセット用のURL作成
$reset_url = "サイトURL/reset-password.php?token=$token";
// メール送信
$to = $email;
$subject = "パスワードリセットのご案内";
$message = "以下のリンクからパスワードをリセットしてください。\n\n" . $reset_url . "\n\n有効期限: 1時間";
// UTF-8エンコーディングを適用
$subject = "=?UTF-8?B?" . base64_encode($subject) . "?=";
$message = mb_convert_encoding($message, "UTF-8", "auto");
// エンコーディング指定(文字化け対策)
$headers = "From: [email protected](サイト管理者のメールアドレス)\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
$headers .= "Content-Transfer-Encoding: base64\r\n";
// メール本文をBase64エンコード(文字化け対策)
$message = base64_encode($message);
if (mail($to, $subject, $message, $headers)) {
echo "リセットメールを送信しました。";
} else {
echo "メールの送信に失敗しました。";
}
} else {
echo "メールアドレスが登録されていません。";
}
}
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
<?php
require_once 'config.php';
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
$db_user = DB_USER;
$db_password = DB_PASS;
try {
$dbh = new PDO($dsn, $db_user, $db_password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['token'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
// トークンをチェック
$stmt = $dbh->prepare("SELECT id FROM users WHERE password_reset_token = ? AND token_expires_at > NOW()");
$stmt->execute([$token]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user) {
// パスワードを更新し、トークンを無効化
$stmt = $dbh->prepare("UPDATE users SET password = ?, password_reset_token = NULL, token_expires_at = NULL WHERE id = ?");
$stmt->execute([$password, $user['id']]);
echo "パスワードが更新されました。";
} else {
echo "無効なトークンまたは期限切れです。";
}
}
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment