better-staridc-MNBT
1<?php
2if (!defined('IN_CRONLITE')) exit();
3
4/**
5 * MNBT Docker 用户独立认证
6 *
7 * 独立于 member.php(admin_token / user_token),使用独立 cookie:docker_token。
8 * - 加密:authcode($user_id . "\t" . $session_hash, 'ENCODE', SYS_KEY)
9 * - session_hash = md5($user_id . $password_hash . SYS_KEY)(改密后旧 cookie 自动失效)
10 * - 密码:password_hash / password_verify(bcrypt)
11 *
12 * 不修改 MPHX/member.php,由 docker/ 控制器自行引入本文件。
13 */
14
15define('MNBT_DOCKER_COOKIE', 'docker_token');
16define('MNBT_DOCKER_COOKIE_TTL', 7 * 86400); // Docker 控制台 cookie 有效期 7 天
17
18/**
19 * 密码哈希(bcrypt)
20 */
21function docker_auth_password_hash($plain)
22{
23 return password_hash((string)$plain, PASSWORD_BCRYPT);
24}
25
26/**
27 * 校验密码
28 */
29function docker_auth_password_verify($plain, $hash)
30{
31 return password_verify((string)$plain, (string)$hash);
32}
33
34/**
35 * 计算 session_hash
36 */
37function docker_auth_session_hash($user_id, $password_hash)
38{
39 return md5((string)$user_id . (string)$password_hash . SYS_KEY);
40}
41
42/**
43 * 写入登录 cookie
44 * @param int $user_id MN_docker_user.id
45 * @param string $password_hash MN_docker_user.password_hash(bcrypt)
46 */
47function docker_auth_login($user_id, $password_hash)
48{
49 $session_hash = docker_auth_session_hash($user_id, $password_hash);
50 $payload = $user_id . "\t" . $session_hash;
51 $cookie_value = authcode($payload, 'ENCODE', SYS_KEY);
52 mnbt_set_auth_cookie(MNBT_DOCKER_COOKIE, $cookie_value, time() + MNBT_DOCKER_COOKIE_TTL);
53}
54
55/**
56 * 登出(清除 docker_token)
57 */
58function docker_auth_logout()
59{
60 mnbt_set_auth_cookie(MNBT_DOCKER_COOKIE, '', time() - 604800);
61}
62
63/**
64 * 获取当前登录的 Docker 用户(含状态/到期校验)
65 * @return array|null MN_docker_user 行;未登录或异常返回 null
66 */
67function docker_auth_current()
68{
69 global $DB;
70 if (empty($_COOKIE[MNBT_DOCKER_COOKIE])) {
71 return null;
72 }
73 $token = authcode(daddslashes($_COOKIE[MNBT_DOCKER_COOKIE]), 'DECODE', SYS_KEY);
74 if ($token === false || $token === '') {
75 return null;
76 }
77 $parts = explode("\t", $token);
78 if (count($parts) !== 2) {
79 return null;
80 }
81 $user_id = (int)$parts[0];
82 $sid = $parts[1];
83 if ($user_id <= 0) {
84 return null;
85 }
86 $row = $DB->get_row_prepare("SELECT * FROM MN_docker_user WHERE id=? limit 1", [$user_id]);
87 if (!$row) {
88 return null;
89 }
90 if (!hash_equals(docker_auth_session_hash($user_id, $row['password_hash']), $sid)) {
91 return null;
92 }
93 return $row;
94}
95
96/**
97 * 要求已登录,否则跳转登录页
98 * @return array 当前 Docker 用户行
99 */
100function docker_auth_require()
101{
102 $row = docker_auth_current();
103 if (!$row) {
104 docker_auth_logout();
105 exit("<script language='javascript'>window.location.href='./login.php';</script>");
106 }
107 // 状态校验
108 if ($row['qk'] === 'paused') {
109 docker_auth_logout();
110 sysmsg('该 Docker 账户已被暂停,请联系管理员');
111 }
112 if ($row['qk'] === 'expired' || $row['qk'] === 'pruned') {
113 docker_auth_logout();
114 sysmsg('该 Docker 账户已到期,请联系管理员续费');
115 }
116 // 到期校验(非永久账号)
117 global $date;
118 if ($row['datae'] !== '0000-00-00' && strtotime($date) - strtotime($row['datae']) > 0) {
119 docker_auth_logout();
120 sysmsg('您的 Docker 账户已到期,已经帮您自动退出登录!刷新即可重新登录');
121 }
122 return $row;
123}
124
125/**
126 * 仅允许未登录访问(如登录页)
127 */
128function docker_auth_guest_only()
129{
130 $row = docker_auth_current();
131 if ($row) {
132 exit("<script language='javascript'>window.location.href='./console.php';</script>");
133 }
134}