94 lines
2.5 KiB
PHP
94 lines
2.5 KiB
PHP
<?php
|
|||
|
|
/**
|
||
|
|
* 简航 SimpleNav —— 后台认证与通用工具
|
||
|
|
*/
|
||
|
|
declare(strict_types=1);
|
||
|
|
require_once dirname(__DIR__) . '/functions.php';
|
||
|
|
|
||
|
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||
|
|
session_start();
|
||
|
|
}
|
||
|
|
|
||
|
|
function admin_count(): int
|
||
|
|
{
|
||
|
|
return (int)db()->query('SELECT COUNT(*) FROM users')->fetchColumn();
|
||
|
|
}
|
||
|
|
|
||
|
|
function current_user(): ?array
|
||
|
|
{
|
||
|
|
if (empty($_SESSION['uid'])) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
$st = db()->prepare('SELECT id, username FROM users WHERE id=?');
|
||
|
|
$st->execute([$_SESSION['uid']]);
|
||
|
|
$u = $st->fetch();
|
||
|
|
return $u ?: null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function require_login(): void
|
||
|
|
{
|
||
|
|
if (!current_user()) {
|
||
|
|
header('Location: ' . url('login.php'));
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function csrf_token(): string
|
||
|
|
{
|
||
|
|
if (empty($_SESSION['csrf'])) {
|
||
|
|
$_SESSION['csrf'] = bin2hex(random_bytes(16));
|
||
|
|
}
|
||
|
|
return $_SESSION['csrf'];
|
||
|
|
}
|
||
|
|
|
||
|
|
function csrf_field(): string
|
||
|
|
{
|
||
|
|
return '<input type="hidden" name="csrf" value="' . e(csrf_token()) . '">';
|
||
|
|
}
|
||
|
|
|
||
|
|
function csrf_check(): void
|
||
|
|
{
|
||
|
|
$t = isset($_POST['csrf']) ? (string)$_POST['csrf'] : '';
|
||
|
|
if (!hash_equals(csrf_token(), $t)) {
|
||
|
|
http_response_code(419);
|
||
|
|
exit('CSRF 校验失败,请刷新页面重试。');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** 统一的后台页面外壳 */
|
||
|
|
function admin_layout(string $active, string $title, string $body): void
|
||
|
|
{
|
||
|
|
$nav = [
|
||
|
|
'sites' => ['网站管理', 'admin/'],
|
||
|
|
'groups' => ['板块管理', 'admin/?p=groups'],
|
||
|
|
'engines' => ['搜索引擎', 'admin/?p=engines'],
|
||
|
|
'settings' => ['系统设置', 'admin/?p=settings'],
|
||
|
|
];
|
||
|
|
?><!DOCTYPE html>
|
||
|
|
<html lang="zh-CN">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title><?= e($title) ?> · <?= e(site_name()) ?> 后台</title>
|
||
|
|
<link rel="stylesheet" href="<?= e(url('assets/css/style.css')) ?>">
|
||
|
|
<link rel="stylesheet" href="<?= e(url('assets/css/admin.css')) ?>">
|
||
|
|
</head>
|
||
|
|
<body class="admin">
|
||
|
|
<header class="topbar">
|
||
|
|
<div class="brand"><a href="<?= e(url()) ?>"><?= e(site_name()) ?></a> <span>后台</span></div>
|
||
|
|
<nav class="topnav">
|
||
|
|
<?php foreach ($nav as $k => $v): ?>
|
||
|
|
<a href="<?= e(url($v[1])) ?>" class="<?= $k === $active ? 'active' : '' ?>"><?= e($v[0]) ?></a>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</nav>
|
||
|
|
<div class="topright">
|
||
|
|
<span class="who"><?= e(current_user()['username'] ?? '') ?></span>
|
||
|
|
<a class="btn ghost" href="<?= e(url('logout.php')) ?>">退出</a>
|
||
|
|
</div>
|
||
|
|
</header>
|
||
|
|
<main class="wrap"><?= $body ?></main>
|
||
|
|
<script src="<?= e(url('assets/js/admin.js')) ?>"></script>
|
||
|
|
</body>
|
||
|
|
</html><?php
|
||
|
|
}
|