本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:备忘md/code-review-todo.md。
SoSite V3.5 代码审查待办清单
来源:第三方 Code Review 对核心文件的审查建议
状态:已逐条核实,等待安排修改
1. Router.php — 命名参数注入隐患
当前代码(第 78-82 行):
if (is_array($handler)) {
list($class, $action) = $handler;
$controller = new $class();
return call_user_func_array([$controller, $action], $params);
}问题:
$params是从路由正则(?P<name>[^/]+)提取的关联数组- PHP 8.0+ 的
call_user_func_array遇到字符串键名会当作命名参数(Named Arguments)传递 - 如果控制器方法形参名与路由参数名不匹配,会抛出
Fatal Error: Unknown named parameter,全站崩溃 - 例如路由
/user/{id}对应方法show($uid),传参就会报错
建议修复:用反射按形参名安全绑定参数
$reflect = new \ReflectionMethod($class, $action);
$methodParams = $reflect->getParameters();
$passedArgs = [];
foreach ($methodParams as $param) {
$paramName = $param->getName();
if (array_key_exists($paramName, $params)) {
$passedArgs[] = $params[$paramName];
} elseif ($param->isDefaultValueAvailable()) {
$passedArgs[] = $param->getDefaultValue();
}
}
return call_user_func_array([$controller, $action], $passedArgs);涉及文件:app/Core/Router.php
优先级:中(当前所有路由参数名与形参名一致,暂未触发,但存在隐患)
2. TemplateCompiler.php — 属性内 XSS 盲区
当前代码:
// 第 146 行 - 变量输出
protected function cbVar($m) {
return '<?php echo htmlspecialchars(' . $this->fixArrayKeys($m[1]) . ' ?? \'\', ENT_QUOTES, \'UTF-8\'); ?>';
}问题:
htmlspecialchars($var, ENT_QUOTES, 'UTF-8')对 HTML 属性内的 XSS 无能为力- 场景 1:
<input value="{$username}">,若$username = test" onclick="alert(1),会闭合属性注入事件 - 场景 2:
<a href="{$url}">,若$url = javascript:alert(1),htmlspecialchars检测不到任何 HTML 特殊字符,直接放行
建议修复:
htmlspecialchars已用ENT_QUOTES+UTF-8,单双引号都处理了(✅ 已满足第一点)- 增加
urlSafe()方法,检测href/src上下文中的变量是否以javascript:/data:开头,是则置空
涉及文件:app/Core/TemplateCompiler.php
优先级:低(当前模板中无 href="{$var}" 用法,作为前置防御)
3. Database.php — busyTimeout 已设置(无需改)
当前代码(第 56 行):
$this->db->busyTimeout(5000);核实:SQLite 的忙等待超时已经是 5000 毫秒,建议里的内容已经实现,无需修改。
涉及文件:app/Core/Database.php
优先级:✅ 无需处理
4. init.php — $GLOBALS 全局变量污染
当前代码:
$GLOBALS['__view'] = new \app\Core\TemplateCompiler();问题:
- 模板引擎实例挂在
$GLOBALS上,存在全局副作用 - 不利于单元测试和代码解耦
建议修复:改为单例模式或由 Controller 基类注入
// TemplateCompiler 中加 getInstance()
private static $instance = null;
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// init.php 中改为
\app\Core\TemplateCompiler::getInstance();涉及文件:app/init.php、app/Core/TemplateCompiler.php
优先级:低(纯重构,功能不变)
5. Auth.php — 重定向地址硬编码
当前代码(第 45、52 行):
header('Location: /login');
header('Location: /admin/verify');问题:
- 如果 SoSite 部署在二级目录(如
http://localhost/sosite/),/login会重定向到http://localhost/login,而不是http://localhost/sosite/login
建议修复:
- 在
config.php中定义BASE_URL常量(自动检测) - Auth 中统一用
BASE_URL . '/login'
涉及文件:app/Helpers/Auth.php、config.php(或 init.php)
优先级:低(当前部署在根目录,不影响)
6. Router.php — 404 页面引用
问题:dispatch() 最后引用了 __DIR__ . '/../Views/errors/404.php',但该文件不存在(实际错误页未创建)。
建议:创建 app/Views/errors/404.php 或在代码中 fallback 为通用 HTML 输出。
涉及文件:app/Core/Router.php(酌情)、app/Views/errors/404.php
优先级:低(当前 fallback 到内联 <h1>404</h1>,不影响功能)
✅ 已验证无需处理
| 文件 | 审查点 | 结论 |
|---|---|---|
Database.php | busyTimeout | 已 5000ms ✅ |
Database.php | WAL 模式 | 已设置 ✅ |
Database.php | 预处理语句 | SQLite/MySQL 都用了 prepare+bind ✅ |
Csrf.php | hash_equals | 已使用,防时序攻击 ✅ |
Autoloader.php | 命名空间映射 | 驼峰→下划线,支持 Plugin\ ✅ |
TemplateCompiler.php | htmlspecialchars | ENT_QUOTES\ |
Auth.php | 半小时二次验证 | 已实现 ✅ |
总结优先级
| 优先级 | 事项 | 影响面 |
|---|---|---|
| 🔴 中 | Router.php 命名参数反射绑定 | PHP 8.0+ 兼容性 |
| 🟢 低 | TemplateCompiler 增加 url 安全过滤 | XSS 前置防御 |
| 🟢 低 | init.php $GLOBALS 改为单例 | 重构 |
| 🟢 低 | Auth.php 硬编码重定向 | 二级目录部署 |
| 🟢 低 | 创建 404 页面 | 用户体验 |
啥时候改,你来安排。