包含:登录失败锁定、90天密码有效期、30分钟会话超时、 强制改密、登录审计日志、屏幕水印、企业背景图、 备案信息固定底部、favicon、JS空集合保护、 会话过期体验优化(403 JSON)、display_errors 关闭、 固定 key 根治 Integrity check failed 等全部改动 注意:config.inc.php/.htaccess/.user.ini 含敏感信息, 通过 .gitignore 排除,勿推送到公开仓库。
72 lines
2.2 KiB
PHP
72 lines
2.2 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace MRBS;
|
||
|
||
/**
|
||
* 等保2.0二级整改:安全审计日志(JSON Lines,文件追加)
|
||
*
|
||
* MRBS 自带 Logger 仅是 PSR-3 外壳(notice/info/debug 只触发 E_USER_NOTICE,
|
||
* 无法落盘),因此这里自行实现一个轻量文件审计器:
|
||
* - 配置项 $audit_log_file 指定日志路径(默认 <web>/audit/security_audit.log)
|
||
* - 超过 20MB 自动轮转一次(保留一份 .old)
|
||
* - 写失败静默(不影响业务),避免审计故障拖垮登录流程
|
||
*
|
||
* 事件类型(event):
|
||
* LOGIN_OK / LOGIN_FAIL / LOGIN_BLOCKED / PWD_CHANGE / PWD_CHANGE_FAIL
|
||
* PWD_RESET / PWD_ADMIN_SET / LOGOUT
|
||
*
|
||
* 日志格式(每行一个 JSON 对象,便于 grep / 导入 SIEM):
|
||
* {"ts":"...","ip":"...","user":"...","event":"...","detail":"..."}
|
||
*/
|
||
class Audit
|
||
{
|
||
public static function log(string $event, ?string $user = null, string $detail = '') : void
|
||
{
|
||
global $audit_log_file, $timezone;
|
||
|
||
$file = $audit_log_file;
|
||
if (empty($file))
|
||
{
|
||
$file = dirname(__DIR__, 2) . '/audit/security_audit.log';
|
||
}
|
||
|
||
// 确保日志目录存在(部署时可能尚未手工创建 audit/ 目录)
|
||
$dir = dirname($file);
|
||
if (!is_dir($dir))
|
||
{
|
||
@mkdir($dir, 0775, true);
|
||
}
|
||
|
||
// 防审计文件无限增长:超过 20MB 轮转一次(保留一份 .old)
|
||
if (is_file($file) && (filesize($file) > 20 * 1024 * 1024))
|
||
{
|
||
@rename($file, $file . '.old');
|
||
}
|
||
|
||
// 统一按 MRBS 配置时区记录时间戳(登录处理发生在 init_area() 之前,
|
||
// 彼时 PHP 默认时区可能仍是 UTC,会导致同一日志两种时区混写)
|
||
$old_tz = date_default_timezone_get();
|
||
if (!empty($timezone))
|
||
{
|
||
@date_default_timezone_set($timezone);
|
||
}
|
||
$ts = date('c');
|
||
if (!empty($old_tz))
|
||
{
|
||
@date_default_timezone_set($old_tz);
|
||
}
|
||
|
||
$record = array(
|
||
'ts' => $ts,
|
||
'ip' => $_SERVER['REMOTE_ADDR'] ?? '-',
|
||
'user' => $user ?? '-',
|
||
'event' => $event,
|
||
'detail' => $detail
|
||
);
|
||
|
||
@file_put_contents($file, json_encode($record, JSON_UNESCAPED_UNICODE) . "\n",
|
||
FILE_APPEND | LOCK_EX);
|
||
}
|
||
}
|