ThinkPHP 跑在 CentOS 上时,真正影响安全性的,往往不是某一个“高阶防护”,而是很多基础项有没有做全。下面按部署和运维最常见的几个环节拆开讲,既保留能直接使用的命令和示例,也说明每一项是在拦什么风险,方便你按优先级逐步加固。
系统与 ThinkPHP 的基础安全项
先把系统和依赖包补到位
CentOS、PHP、MySQL 这类底层组件如果长期不更新,很多已知漏洞会直接留在生产环境里。最基础的一步,就是定期执行下面的更新命令:
sudo yum update -y
这一步看起来普通,但它决定的是你是否还暴露在已经公开、甚至已有现成利用脚本的漏洞之下。
生产环境别暴露调试和报错细节
PHP 的 display_errors 必须设为 Off,否则一旦程序报错,服务器路径、数据库连接信息等细节可能直接出现在浏览器里。
ThinkPHP 本身的调试模式也要关闭,确保 app_debug 为 false。调试信息越完整,攻击者越容易定位控制器、配置项和异常入口。
把关键参数收紧,而不是继续用默认值
生产环境建议至少明确限制以下 PHP 参数:

memory_limit:256Mmax_execution_time:30秒upload_max_filesize:2M
这些限制的意义,不只是节省资源,更是减少异常请求、恶意上传和超时占用带来的攻击窗口。
应用密钥和模块也要同步清理
APP_KEY 不要继续使用默认值,可以用下面的命令生成高强度随机字符串:

openssl rand -hex 32
这个密钥会影响 Cookie、Session 等数据的加密强度,一旦弱密钥或默认密钥被猜中,相关保护基本失效。
另外,application 目录下未使用的模块应删除或重命名,配置里也同步注释掉。对外暴露的入口越少,攻击面越小。
输入校验与 SQL 注入防护怎么做
优先用 ThinkPHP 验证器做统一校验
表单、接口参数、后台录入数据,最怕的是不同控制器各写一套零散判断。更稳妥的做法是使用 ThinkPHP 官方 Validate 类,集中定义字段规则,例如必填、长度和邮箱格式:
$validate = new thinkValidate([
'username' => 'require|max:25|min:3',
'email' => 'require|email'
]);
if (!$validate->check(input('post.'))) {
return json(['error' => '输入数据不合法']);
}
这样做的好处是,规则可复用,控制器逻辑也不会因为散落的 if 判断变得难维护。
全局过滤适合挡住最基础的脏数据
在 application/common.php 中配置全局过滤规则,例如 strip_tags 去标签、htmlentities 转义特殊字符,可以让输入数据在进入业务逻辑前先过一遍基础清洗。
这不能替代精确校验,但能减少明显的 HTML 注入和异常字符输入。
数据库查询尽量走框架的参数绑定能力
SQL 注入最常见的问题,还是把变量直接拼进 SQL。ThinkPHP 的查询构造器和模型已经基于 PDO 预处理与参数绑定,例如:
Db::table('user')->where('id', $id)->find()User::get($id)
这类写法通常比手工拼接更稳。如果确实要写原生 SQL,也要使用 占位符绑定参数,避免把外部输入直接拼到查询语句里。
敏感数据存储与传输链路加固
数据库里不要留明文敏感信息
密码、手机号等敏感字段不应明文存储。文中给出的做法是使用 thinkfacadeCrypt 的 encrypt 和 decrypt 进行加解密。即使数据库被拖库,攻击者拿到的也不是可直接使用的原始数据。
数据库账号、端口和权限要最小化
数据库密码应包含大小写、数字和特殊字符;默认端口 3306 可以调整;数据库账户权限只保留应用实际需要的范围,例如 SELECT、INSERT,不要直接给 all privileges。
这一步的价值在于,即使应用层出现问题,也尽量把数据库侧的损失范围压小。
HTTPS 是线上环境的默认项
站点对外提供服务时,应配置 Nginx 或 Apache 开启 443 端口,并使用 Let's Encrypt 证书启用 HTTPS。这样可以保护登录态、表单内容和接口数据,减少传输链路上被窃听或篡改的风险。
文件上传与目录权限如何收口
上传文件先限制类型和大小
文件上传是 ThinkPHP 项目里很常见、也很容易出问题的入口。可以直接利用 File 类做校验,限制扩展名、大小和 MIME 类型:
$file = request()->file('file');
$info = $file->validate(['size' => 1024*1024*2, 'ext' => 'jpg,png,gif'])->move(public_path('uploads'));
if (!$info) {
return json(['error' => '文件大小或类型错误']);
}
这里的限制值保留为原文建议:大小 2M,扩展名为 jpg,png,gif。这类白名单策略,通常比事后拦截更有效。
上传目录不要直接暴露为可执行路径
上传文件尽量不要直接放在 Web 根目录内。原文建议放到 public/uploads 之外,再通过 Nginx 或 Apache 做别名访问。这样即便有人绕过校验上传了恶意脚本,也很难通过 URL 直接执行。
目录权限和运行目录访问控制要分开看
项目目录可用 chmod -R 755 设置权限,Web 服务器用户如 nginx、apache 只保留必要读取权限,减少文件被篡改的机会。
runtime 目录存放缓存和日志,也建议使用 755,并在 Nginx 中明确禁止外部访问:
location ~ ^/runtime/ { deny all; }
这一条的重点是,运行时文件即使存在于项目中,也不应暴露为可直接访问的 URL 资源。
运行环境里的防火墙、会话与防暴力破解
先把服务器开放面缩到最小
使用 firewalld 时,只保留 HTTP 80 和 HTTPS 443 这类必要端口即可,像 FTP、Telnet 等无关端口应关闭。原文给出的命令是:
firewall-cmd --permanent --add-service=http --add-service=https
端口暴露越少,可被扫描和尝试利用的入口就越少。
SSH 登录策略直接影响主机失陷风险
修改 /etc/ssh/sshd_config 时,建议至少做两项:
PermitRootLogin no:禁止 root 直接登录ClientAliveInterval 300:设置空闲超时
这两项不能彻底解决暴力破解问题,但能明显降低高危默认配置带来的风险。
会话配置别忽略登录后的 ID 更新
在 config/session.php 中设置 encrypt = true,可让 Session 数据以加密形式存储。与此同时,用户登录成功后应主动执行:
session_regenerate_id(true)
这样旧的 Session ID 会失效,可防止会话固定攻击继续利用既有标识。
高频登录尝试需要单独限速
对于登录接口,建议使用 iptables 或 fail2ban 按 IP 限制请求频率。原文建议的阈值是“每分钟超过 10 次登录尝试就自动封禁”。这类限速措施虽然简单,但对撞库和暴力猜密场景非常有效。
综合来看,CentOS 下的 ThinkPHP 安全建设,更像是一套分层收口方案:先堵已知漏洞和调试泄露,再管住输入、数据库、文件和会话,最后用防火墙与限速把运行环境补齐。只要这些基础项持续维护,SQL 注入、XSS、CSRF、恶意上传和暴力破解这类常见风险,基本都能被压到较低水平。








