NewHome/includes/auth.php

110 lines
3.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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, string $deviceClient = ''): bool
{
$uaRaw = (string) ($_SERVER['HTTP_USER_AGENT'] ?? '');
if (hp_verify_user($username, $plain)) {
session_regenerate_id(true);
$_SESSION['admin'] = $username;
// 记录本次登录信息(供后台“登录信息”卡片展示)
$_SESSION['login_at'] = date('Y-m-d H:i:s');
$_SESSION['login_ip'] = client_ip();
$_SESSION['login_ua'] = login_ua_brief($uaRaw);
$_SESSION['login_device'] = login_device_brief($deviceClient, $uaRaw);
login_log_write($username, 'ok', $deviceClient);
return true;
}
login_log_write($username, 'fail', $deviceClient);
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']);
}