102 lines
2.6 KiB
PHP
102 lines
2.6 KiB
PHP
<?php
|
||
/**
|
||
* auth.php —— 后台登录会话工具
|
||
* 密码存储算法(按需求):md5(base64(明文))
|
||
*/
|
||
require_once __DIR__ . '/db.php';
|
||
|
||
if (session_status() === PHP_SESSION_NONE) {
|
||
session_start();
|
||
}
|
||
|
||
/** 是否已登录 */
|
||
function is_logged_in(): bool
|
||
{
|
||
return !empty($_SESSION['admin']);
|
||
}
|
||
|
||
/** 未登录则跳转登录页(后台各页顶部调用) */
|
||
function require_login(string $loginPage = 'login.php'): void
|
||
{
|
||
if (!is_logged_in()) {
|
||
header('Location: ' . $loginPage);
|
||
exit;
|
||
}
|
||
}
|
||
|
||
/** 计算需求规定的密码散列:先 base64 再 md5 */
|
||
function hp_password_hash(string $plain): string
|
||
{
|
||
return md5(base64_encode($plain));
|
||
}
|
||
|
||
/** 验证用户 */
|
||
function hp_verify_user(string $username, string $plain): bool
|
||
{
|
||
$st = db()->prepare('SELECT password_hash FROM users WHERE username = ? LIMIT 1');
|
||
$st->execute([$username]);
|
||
$row = $st->fetch();
|
||
if (!$row) {
|
||
return false;
|
||
}
|
||
return hash_equals($row['password_hash'], hp_password_hash($plain));
|
||
}
|
||
|
||
/** 执行登录(成功返回 true) */
|
||
function hp_login(string $username, string $plain): bool
|
||
{
|
||
if (hp_verify_user($username, $plain)) {
|
||
session_regenerate_id(true);
|
||
$_SESSION['admin'] = $username;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/** 修改当前用户密码 */
|
||
function hp_change_password(string $oldPlain, string $newPlain): array
|
||
{
|
||
if (!is_logged_in()) {
|
||
return [false, '未登录'];
|
||
}
|
||
if (!hp_verify_user((string)$_SESSION['admin'], $oldPlain)) {
|
||
return [false, '原密码不正确'];
|
||
}
|
||
if (strlen($newPlain) < 6) {
|
||
return [false, '新密码至少 6 位'];
|
||
}
|
||
$st = db()->prepare('UPDATE users SET password_hash = ? WHERE username = ?');
|
||
$st->execute([hp_password_hash($newPlain), (string)$_SESSION['admin']]);
|
||
return [true, '密码修改成功'];
|
||
}
|
||
|
||
/** 退出登录 */
|
||
function hp_logout(): void
|
||
{
|
||
$_SESSION = [];
|
||
if (ini_get('session.use_cookies')) {
|
||
$p = session_get_cookie_params();
|
||
setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'], $p['httponly']);
|
||
}
|
||
session_destroy();
|
||
}
|
||
|
||
/** CSRF token */
|
||
function csrf_token(): string
|
||
{
|
||
if (empty($_SESSION['csrf'])) {
|
||
$_SESSION['csrf'] = bin2hex(random_bytes(16));
|
||
}
|
||
return (string)$_SESSION['csrf'];
|
||
}
|
||
|
||
function csrf_field(): string
|
||
{
|
||
return '<input type="hidden" name="csrf" value="' . htmlspecialchars(csrf_token(), ENT_QUOTES, 'UTF-8') . '">';
|
||
}
|
||
|
||
function csrf_verify(): bool
|
||
{
|
||
return isset($_POST['csrf']) && is_string($_POST['csrf']) && hash_equals(csrf_token(), $_POST['csrf']);
|
||
}
|