[Harson] PHP를 사용하여 간단한 Remember Me(자동 로그인) 구현
개시하다
주변에서 몰랐던 열등감을 인증하기 위해 아래 글 두 편에 이어 리멤버미(자동 로그인 기능)를 시행해 봤다.
누구한테 도움이 됐으면 좋겠어요.
실장 프로세스
파일 구성
.
├─ database.php
├─ login.php
├─ logout.php
├─ show_login_form.php
├─ show_mypage.php
└─ views
├── login_form.php
└── mypage.php
사용할 테이블
사용자 테이블
열 이름
시험을 준비하다
id
주 키워드
register_token
가등기 때 사용한다.고유 식별 사용자
register_token_sent_at
임시 등록에 사용되는 유효기간 관리
register_token_verified_at
등록 시 업데이트
password
remember_token
remember me를 구현하는 데 사용됩니다.고유 식별 사용자
status
num형.tentative: 임시 등록,puvlic:본 로그인
created_at
updated_at
제작된 DDL은 여기(MySQL로 가정)
CREATE TABLE `users` (
`id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
`email` VARCHAR(50) UNIQUE NOT NULL,
`register_token` VARCHAR(80),
`register_token_sent_at` DATETIME,
`register_token_verified_at` DATETIME,
`password` VARCHAR(80),
`remember_token` VARCHAR(80),
`status` ENUM('tentative', 'public') NOT NULL DEFAULT 'tentative',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
!register_token、register_token_sent_at、register_token_verified_at,status는 새로운 로그인 기능을 실시하는 글에서 사용하기 때문에 이번 실시에 참여하지 않습니다.
!
전제는 한 사람도 users 테이블에 등록할 수 있다는 것이다.
만약 누군가가 자신의 환경에서 함께 읽어보려고 한다면, 나는 SQL로 유입될 준비를 할 것이다.
로그인 암호는 "password"입니다.
유입용 SQL
INSERT INTO `users` (`id`, `email`, `register_token`, `register_token_sent_at`, `register_token_verified_at`, `password`, `status`, `created_at`, `updated_at`)
VALUES
(1,'[email protected]','45085a3ce32c6623c4159dc3e202007c6ef26d0a8201ab9802426a35a0bc2474','2022-03-27 12:21:41','2022-03-27 12:21:58','$2y$10$BmxkPc6uMmRyWvgvpUUs1OOlSuplcyLb6FzQEooh1LHS/aPUt6no2','public','2022-03-27 12:21:41','2022-03-27 16:38:58');
1. 메일 주소와 비밀번호가users표의 기록에 부합되면 해당 사용자로 로그인
show_login_form.php
<?php
session_start();
// formに埋め込むcsrf tokenの生成
if (empty($_SESSION['_csrf_token'])) {
$_SESSION['_csrf_token'] = bin2hex(random_bytes(32));
}
// 本登録フォームを読み込む
require_once './views/login_form.php';
창 부분 (form 탭에서 선택)views/login_form.php
<p>ログイン</p>
<form action="login.php" method="POST">
<input type="hidden" name="_csrf_token" value="<?= $_SESSION['_csrf_token']; ?>">
<label>メールアドレス
<input type="email" name="email">
</label>
<br>
<label>パスワード
<input type="password" name="password">
</label>
<br>
<label>ログイン情報を記憶する
<input type="checkbox" name="remember_me">
</label>
<br>
<button type="submit">ログイン</button>
</form>
2. 만약에 메일 주소가 users표에 로그인되면 메일 발송 완료 화면과 종료를 표시합니다
login.php
<?php
session_start();
require_once './database.php';
$pdo = getPdo();
$request = filter_input_array(INPUT_POST);
// csrf tokenが正しければOK
if (
empty($request['_csrf_token'])
|| empty($_SESSION['_csrf_token'])
|| $request['_csrf_token'] !== $_SESSION['_csrf_token']
) {
exit('不正なリクエストです');
}
// 本来はここでメールアドレスとパスワードのバリデーションをする
// 入力されたメールアドレスに合致するユーザーを取得
$sql = 'SELECT * FROM users WHERE `email` = :email AND `status` = :status';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':email', $request['email'], \PDO::PARAM_STR);
$stmt->bindValue(':status', 'public', \PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(\PDO::FETCH_OBJ);
// 「メールアドレスが間違っている」のようにどちらが間違っているのか表示すると、
// 別人のアカウントでログインしようとする悪意あるユーザーに、
// 「メールアドレスが間違っている」「パスワードは間違っていない」という情報を与えてしまうので、明示しない
if (
!$user
|| !password_verify($request['password'], $user->password)
) {
exit('登録情報が間違っています。');
}
// セッションが有効な間はログイン済みとなる
$_SESSION['user_id'] = $user->id;
// 「ログイン情報を記憶する」をチェックしていなければ、このままマイページへ
if (empty($request['remember_me'])) {
header('Location: ./show_mypage.php');
exit();
}
코드에 나오는 데이터 베이스.php의 내용은 여기에 있습니다.database.php
database.php
<?php
function getPdo()
{
$dsn = 'mysql:host=localhost;dbname=zenn;charset=utf8mb4';
$options = [
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
];
try {
return new \PDO($dsn, 'root', 'root', $options);
} catch (\PDOException $e) {
exit($e->getMessage());
}
}
3. 스토리지 로그인 정보를 검토한 경우 Remember Me(자동 로그인) 처리
login.php(※ 2. 파일의 계속)
// ランダムな文字列のtokenを生成
$rememberToken = bin2hex(random_bytes(32));
// 暗号化したremember tokenを保存
$sql = 'UPDATE users SET `remember_token` = :remember_token WHERE `email` = :email';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':remember_token', md5($rememberToken), \PDO::PARAM_STR);
$stmt->bindValue(':email', $request['email'], \PDO::PARAM_STR);
$stmt->execute();
// cookieのオプション
$options = [
'expires' => time() + 60 * 60 * 24 * 365, // cookieの有効期限を1年間に設定
'path' => '/', // 有効範囲を「ドメイン配下全て」に設定
'httponly' => true // HTTPを通してのみcookieにアクセス可能(JavaScriptからのアクセスは不可となる)
];
setcookie('remember_token', $rememberToken, $options);
header('Location: ./show_mypage.php');
exit();
4. 내 페이지를 방문할 때 두 가지 로그인을 확인하고 내 페이지를 표시한다
show_mypage.php(※ 3. 파일의 계속)
<?php
session_start();
require_once './database.php';
$pdo = getPdo();
// (1) セッションにユーザーIDが保存されている場合
if (isset($_SESSION['user_id'])) {
// セッションに保存されたユーザーIDに合致するユーザーを取得
$sql = 'SELECT * FROM users WHERE `id` = :id AND `status` = :status';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':id', $_SESSION['user_id'], \PDO::PARAM_INT);
$stmt->bindValue(':status', 'public', \PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(\PDO::FETCH_OBJ);
// (2) セッションのユーザーIDは破棄されているが、cookieにremember_tokenが保存されている場合
} else if (isset($_COOKIE['remember_token'])) {
// usersテーブルに保存されている remember_token は md5() で暗号化されているので、同様に暗号化した token をWHERE句に指定する
$sql = 'SELECT * FROM users WHERE `remember_token` = :remember_token AND `status` = :status';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':remember_token', md5($_COOKIE['remember_token']), \PDO::PARAM_STR);
$stmt->bindValue(':status', 'public', \PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(\PDO::FETCH_OBJ);
}
// ユーザーが一致しなければ、ログインフォームへ
if (empty($user)) {
header('Location: ./show_login_form.php');
exit();
}
// ユーザーIDをセッションに保存してログイン済みとする
$_SESSION['user_id'] = $user->id;
// formに埋め込むcsrf tokenの生成
if (empty($_SESSION['_csrf_token'])) {
$_SESSION['_csrf_token'] = bin2hex(random_bytes(32));
}
require_once './views/mypage.php';
내 페이지mypage.php
<p><?= $user->email ?>さんのマイページ</p>
<form action="logout.php" method="POST">
<input type="hidden" name="_csrf_token" value="<?= $_SESSION['_csrf_token']; ?>">
<button type="submit">ログアウトはこちら</button>
</form>
쿠키를 확인하려면 도구→Application 태그→Storage→Cookies를 확인하십시오.(1) 세션에 사용자 ID가 저장된 경우
쿠키에 저장된 것은 세션 쿠키뿐입니다.
먼저 브라우저를 닫고 브라우저를 다시 시작한 다음 제 페이지로 바로 들어가십시오.
세션은 브라우저가 끝난 후에 버려집니다. 따라서 로그아웃 상태로 들어가 로그인 창을 표시합니다.
(2) 세션의 사용자 ID가 폐기되었지만 remember cookietoken이 저장된 경우
쿠키에 쿠키, 리멤버가 들어갔어요.token이 저장되었습니다.
쿠키는 유효기간을 1년으로 설정하여 브라우저를 닫아도 폐기되지 않습니다.
브라우저를 끝낸 후 다시 시작합니다. 내 페이지에 들어오면remmeber값이 일치하는 사용자로token에 로그인합니다.
※session_start를 발표했기 때문에 PHPSESSID 자체가 발매되었습니다.
5. 내 페이지의 로그아웃 단추를 눌렀을 때users표의remembertoken 열을 NULL로 업데이트하고 로그아웃
logout.php
<?php
session_start();
require_once './database.php';
$pdo = getPdo();
$request = filter_input_array(INPUT_POST);
// csrf tokenが正しければOK
if (
empty($request['_csrf_token'])
|| empty($_SESSION['_csrf_token'])
|| $request['_csrf_token'] !== $_SESSION['_csrf_token']
) {
exit('不正なリクエストです');
}
// remember_tokenをNULLにする
$sql = 'UPDATE users SET remember_token = NULL WHERE `id` = :id';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':id', $_SESSION['user_id'], \PDO::PARAM_INT);
$stmt->execute();
// remeber_tokenをcookieから削除
setcookie('remember_token', '', time() - 6000, '/');
// 以下、セッションの削除処理
// セッション変数を初期化(メモリから削除するため)
$_SESSION = [];
// セッションクッキーを削除
setcookie('PHPSESSID', '', time() - 6000, '/');
// セッションファイル(セッションの実データ)を削除
session_destroy();
// ログインフォームへ
header('Location: ./show_login_form.php');
exit();
끝까지 읽어주셔서 감사합니다!
Reference
이 문제에 관하여([Harson] PHP를 사용하여 간단한 Remember Me(자동 로그인) 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/syamozipc/articles/php_remember_me텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)