Become a sponsor

上线前必检
以下安全配置在生产环境上线前必须完成,否则存在严重安全风险。
| 项目 | 操作 | 检查命令 |
|---|---|---|
| JWT 密钥 | .env 中 JWT.SECRET 修改为强随机字符串 | grep JWT.SECRET .env |
| 调试模式 | .env 中 APP_DEBUG = false | grep APP_DEBUG .env |
| 错误信息 | .env 中 SHOW_ERROR_MSG = false | grep SHOW_ERROR_MSG .env |
| CORS | .env 中 CORS.ALLOW_ORIGIN 限制为实际域名 | grep CORS .env |
| 数据库密码 | 修改默认 root 密码 | mysql -u root -p |
| Redis 密码 | 设置 requirepass | redis-cli CONFIG GET requirepass |
| HTTPS | 启用 SSL 证书 | curl -I https://your-domain.com |
# -----------------------------------------------------------------------------
# 生成 JWT 签名密钥(32 字节 = 64 个十六进制字符)
# -----------------------------------------------------------------------------
# random_bytes(32) → 生成 32 字节的密码学安全随机数
# bin2hex() → 转为十六进制字符串(便于复制粘贴到 .env)
php -r "echo bin2hex(random_bytes(32));"
# -----------------------------------------------------------------------------
# 生成 MySQL 密码(16 字节 = 32 个十六进制字符)
# -----------------------------------------------------------------------------
php -r "echo bin2hex(random_bytes(16));"
# -----------------------------------------------------------------------------
# 生成 Redis 密码(16 字节 = 32 个十六进制字符)
# -----------------------------------------------------------------------------
php -r "echo bin2hex(random_bytes(16));"# =============================================================================
# Nginx 安全加固配置(添加到 server 块内)
# =============================================================================
# 禁止访问隐藏文件(.env、.git、.htaccess 等)
location ~ /\. {
deny all;
}
# 禁止上传目录执行 PHP(防止 Webshell 攻击)
location ~ /uploads/.*\.php$ {
deny all;
}
# -----------------------------------------------------------------------------
# 安全响应头
# -----------------------------------------------------------------------------
# X-Frame-Options → 禁止被嵌入 iframe(防点击劫持)
# X-Content-Type-Options → 禁止浏览器 MIME 类型嗅探
# X-XSS-Protection → 启用浏览器 XSS 过滤
# Referrer-Policy → 控制 Referer 头信息泄露
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 隐藏 Nginx 版本号(防止攻击者针对性利用已知漏洞)
server_tokens off;; =============================================================================
; php.ini 生产环境安全配置
; =============================================================================
; 配置路径:/etc/php/8.2/fpm/php.ini
; 生效命令:sudo systemctl restart php8.2-fpm
; =============================================================================
expose_php = Off ; 隐藏 PHP 版本号(防止针对性攻击)
display_errors = Off ; 不向浏览器显示错误(防止 SQL/路径泄露)
log_errors = On ; 记录错误到日志文件(便于排查)
allow_url_fopen = Off ; 禁止 fopen 打开远程 URL(防 SSRF)
disable_functions = exec,passthru,shell_exec,system,proc_open ; 禁用危险系统函数# -----------------------------------------------------------------------------
# 项目目录(owner 可读写执行,group/others 可读和执行)
# -----------------------------------------------------------------------------
chmod -R 755 /www/api/ # 目录 755,文件自动 644
chown -R www-data:www-data /www/api/ # owner 设为 Web 服务器用户
# -----------------------------------------------------------------------------
# 运行时目录(必须可写 — ThinkPHP 缓存、日志、编译模板)
# -----------------------------------------------------------------------------
chmod -R 777 /www/api/runtime/ # 777 确保 PHP-FPM 可写入
# -----------------------------------------------------------------------------
# 上传目录(必须可写 — 用户上传文件存储位置)
# -----------------------------------------------------------------------------
chmod -R 755 /opt/data/uploads/ # 目录可写
chown -R www-data:www-data /opt/data/uploads/ # owner 设为 Web 服务器用户
# -----------------------------------------------------------------------------
# .env 文件(仅 owner 可读 — 包含数据库密码等敏感信息)
# -----------------------------------------------------------------------------
# 600 = owner 可读写,group/others 无权限
chmod 600 /www/api/.env-- =============================================================================
-- MySQL 安全加固 SQL
-- =============================================================================
-- 在 MySQL 命令行中执行:mysql -u root -p
-- =============================================================================
-- 修改 root 密码(替换 strong_password_here 为实际强密码)
ALTER USER 'root'@'localhost' IDENTIFIED BY 'strong_password_here';
-- 创建应用专用数据库用户(生产环境不应用 root 连接应用)
-- rxthinkcmf_app → 应用专用用户名
-- app_password → 应用专用密码
CREATE USER 'rxthinkcmf_app'@'localhost' IDENTIFIED BY 'app_password';
-- 授权应用用户只能访问项目数据库(最小权限原则)
-- rxthinkcmf.thinkphp6.elevue.* → 该项目数据库的所有表
GRANT ALL PRIVILEGES ON `rxthinkcmf.thinkphp6.elevue`.* TO 'rxthinkcmf_app'@'localhost';
FLUSH PRIVILEGES; -- 刷新权限使配置生效
-- 禁止远程 root 登录(只允许本地连接)
-- Host NOT IN (...) → 删除非本地的 root 账户
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
FLUSH PRIVILEGES;# =============================================================================
# redis.conf 安全配置
# =============================================================================
# 配置路径:/etc/redis/redis.conf
# 生效命令:sudo systemctl restart redis
# =============================================================================
requirepass your_strong_redis_password ; 设置访问密码(必须设置)
bind 127.0.0.1 ; 只监听本地(禁止外部直接访问)
protected-mode yes ; 启用保护模式(无密码时拒绝外部连接)
# 禁用危险命令(防止误操作清空数据或修改配置)
# 将命令重命名为空字符串 = 禁用该命令
rename-command FLUSHALL "" ; 禁用 FLUSHALL(清空所有数据库)
rename-command FLUSHDB "" ; 禁用 FLUSHDB(清空当前数据库)
rename-command CONFIG "" ; 禁用 CONFIG(防止运行时修改配置)#!/bin/bash
# =============================================================================
# check_security.sh — 生产环境安全检查脚本
# =============================================================================
# 用途:自动检查 .env 中的安全配置项是否符合生产要求
# 用法:cd /www/api && bash check_security.sh
# =============================================================================
echo "=== 安全检查 ==="
# -----------------------------------------------------------------------------
# 检查 APP_DEBUG 是否关闭
# -----------------------------------------------------------------------------
# grep "APP_DEBUG" .env → 从 .env 文件中提取 APP_DEBUG 行
# grep -v "#" → 排除注释行
# cut -d= -f2 → 以 = 为分隔符取第 2 部分(值)
# tr -d ' ' → 去除空格
debug=$(grep "APP_DEBUG" .env | grep -v "#" | cut -d= -f2 | tr -d ' ')
if [ "$debug" = "true" ]; then
echo "❌ APP_DEBUG 未关闭(生产环境必须为 false)"
else
echo "✓ APP_DEBUG 已关闭"
fi
# -----------------------------------------------------------------------------
# 检查 JWT 密钥长度
# -----------------------------------------------------------------------------
# sed -n '/\[JWT\]/,/^\[/p' → 提取 .env 中 [JWT] 到下一个 [...] 之间的内容
# grep "^SECRET" → 取 SECRET 行
# ${#secret} → 获取字符串长度
secret=$(sed -n '/\[JWT\]/,/^\[/p' .env | grep "^SECRET" | cut -d= -f2 | tr -d ' ')
if [ ${#secret} -lt 32 ]; then
echo "❌ JWT 密钥太短(建议32字节以上,当前 ${#secret} 字符)"
else
echo "✓ JWT 密钥长度足够(${#secret} 字符)"
fi
# -----------------------------------------------------------------------------
# 检查 CORS 是否允许所有来源
# -----------------------------------------------------------------------------
cors=$(sed -n '/\[CORS\]/,/^\[/p' .env | grep "^ALLOW_ORIGIN" | cut -d= -f2 | tr -d ' ')
if [ "$cors" = "*" ]; then
echo "⚠ CORS 允许所有来源(生产环境建议限制为实际域名)"
else
echo "✓ CORS 已限制来源"
fi
echo "=== 检查完成 ==="