此文章为XIUNOX版本重构审计时发现问题,XIUNOX版本已优化修复此问题。分享出来方便后续想基于xiuno bbs4.0.4版本制作维护版本或插件模板等需求的开发者和站长参考。
现象
Xiuno BBS 4.0.4 没有真正的 Model-View-Controller 分层架构。route/*.php 文件同时承担了 Controller(参数校验、权限检查)、Model(业务逻辑、数据读写调用)和 View 调度(直接 include 模板)三重职责,业务逻辑与 HTML 模板渲染强耦合,无独立 Controller 基类、无 Model 抽象层、View 仅为原始 .htm 模板含大段 PHP 代码。
源码证据
1. 入口路由 switch 直接 include route 文件,无 Controller 抽象
文件:xiunobbs_4.0.4/index.inc.php 第 53-79 行
if(!defined('SKIP_ROUTE')) {
switch ($route) {
case 'index': include _include(APP_PATH.'route/index.php'); break;
case 'thread': include _include(APP_PATH.'route/thread.php'); break;
case 'forum': include _include(APP_PATH.'route/forum.php'); break;
case 'user': include _include(APP_PATH.'route/user.php'); break;
case 'my': include _include(APP_PATH.'route/my.php'); break;
case 'attach': include _include(APP_PATH.'route/attach.php'); break;
case 'post': include _include(APP_PATH.'route/post.php'); break;
case 'mod': include _include(APP_PATH.'route/mod.php'); break;
case 'browser': include _include(APP_PATH.'route/browser.php'); break;
default:
include _include(APP_PATH.'route/index.php'); break;
}
}
2. route/user.php 同时承担参数校验、业务逻辑、模板渲染
文件:xiunobbs_4.0.4/route/user.php 第 52-104 行
} elseif($action == 'login') {
if($method == 'GET') {
$referer = user_http_referer();
$header['title'] = lang('user_login');
include _include(APP_PATH.'view/htm/user_login.htm');
} else if($method == 'POST') {
$email = param('email');
$password = param('password');
empty($email) AND message('email', lang('email_is_empty'));
if(is_email($email, $err)) {
$_user = user_read_by_email($email);
empty($_user) AND message('email', lang('email_not_exists'));
} else {
$_user = user_read_by_username($email);
}
!is_password($password, $err) AND message('password', $err);
md5($password.$_user['salt']) != $_user['password'] AND message('password', lang('password_incorrect'));
user_update($_user['uid'], array('login_ip'=>$longip, 'login_date' =>$time , 'logins+'=>1));
$uid = $_user['uid'];
$_SESSION['uid'] = $uid;
user_token_set($_user['uid']);
message(0, lang('user_login_successfully'));
}
}
3. 模板文件 post.htm 中嵌入大量 PHP 业务逻辑
文件:xiunobbs_4.0.4/view/htm/post.htm 第 3-37 行
<?php
if($route == 'thread' && $action == 'create') {
$form_title = lang('thread_create');
$form_action = url("thread-create");
$form_submit_txt = lang('thread_create');
$form_subject = '';
$form_message = '';
$form_doctype = 1;
$isfirst = 1;
$quotepid = 0;
$location = url("forum-'+jfid.checked()+'");
$filelist = array();
} elseif($route == 'post' && $action == 'update') {
$form_title = lang('post_update');
}
4. Model 层仅为函数集 合(func.php),无类、无继承、无 ORM
文件:xiunobbs_4.0.4/model/user.func.php 第 11-37 行
function user__create($arr) {
$r = db_insert('user', $arr);
return $r;
}
function user__update($uid, $update) {
$r = db_update('user', array('uid'=>$uid), $update);
return $r;
}
function user__read($uid) {
$user = db_find_one('user', array('uid'=>$uid));
return $user;
}
function user__delete($uid) {
$r = db_delete('user', array('uid'=>$uid));
return $r;
}
风险等级与结论
架构缺陷(严重)
危害:
- 单一职责原则被破坏,
route/*.php 文件动辄数百行混合代码,可维护性极差
- 无法独立测试业务逻辑(无 Model 类、无依赖注入)
- 模板中嵌入 PHP 业务逻辑导致前后端协作困难,无法更换模板引擎
- 缺少 Controller 基类导致公共逻辑(鉴权、CSRF、参数校验)只能在每个 route 文件中重复
- 模型层为函数集 合而非对象,无法表达关联关系、事务、生命周期
修复建议:
- 引入轻量级 MVC 框架(或抽象 BaseController、BaseModel、BaseView)
- 将
route/*.php 拆分为 Controller 类(如 UserController),方法对应 action
- 将
model/*.func.php 重构为 Model 类,封装属性、关联关系、查询构造器
- 模板文件移除 PHP 业务逻辑,仅保留展示层变量替换