CarefreeCMS 文档CarefreeCMS 文档
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
指南
  • 内容管理
  • 多站点管理
  • AI文章生成
  • SEO优化
  • 静态化生成
API
  • FAQ
  • 更新日志
  • 贡献指南
  • v1.3.0
  • v1.2.0
  • v1.1.0
GitHub
  • 开始使用

    • 介绍
    • 安装指南
    • 快速开始
    • 系统配置
  • 基础功能

    • 文章管理
    • 分类管理
    • 标签管理
    • 单页管理
    • 媒体库
  • 高级功能

    • 模板开发
    • 静态化生成
    • 搜索功能
    • 权限管理
    • 用户管理
  • AI 功能

    • AI 服务商配置
    • AI 模型配置
    • 提示词工程
  • 系统管理

    • 定时任务
    • 日志管理
    • 安全指南
    • 性能优化

安全指南

本文介绍 CarefreeCMS 的安全最佳实践和配置建议。

身份验证

JWT 认证

CarefreeCMS 使用 JWT(JSON Web Token)进行用户认证。

配置 JWT 密钥

编辑 .env 文件:

JWT_SECRET=your-secret-key-here
JWT_EXPIRE=7200

建议:

  • 使用强随机字符串作为密钥
  • 定期更换密钥
  • 不要在代码中硬编码密钥

Token 刷新

Token 过期后需要刷新:

const refreshToken = async () => {
  const res = await axios.post('/api/auth/refresh', {
    refresh_token: localStorage.getItem('refresh_token')
  })
  localStorage.setItem('token', res.data.token)
}

密码安全

密码策略

在 config/app.php 中配置:

'password' => [
    'min_length' => 8,
    'require_uppercase' => true,
    'require_lowercase' => true,
    'require_numbers' => true,
    'require_special_chars' => true,
],

密码加密

使用 PHP 的 password_hash() 函数:

$password = password_hash($input_password, PASSWORD_BCRYPT);

权限控制

RBAC 权限系统

基于角色的访问控制(RBAC)。

角色定义

// 超级管理员
'admin' => [
    'name' => '超级管理员',
    'permissions' => ['*']
],

// 编辑
'editor' => [
    'name' => '编辑',
    'permissions' => [
        'article.create',
        'article.update',
        'article.delete'
    ]
]

权限检查

// 检查权限
if (!hasPermission('article.delete')) {
    throw new Exception('无权限');
}

// 中间件
Route::middleware(['auth', 'permission:article.create'])
    ->post('/api/articles', 'ArticleController@create');

数据安全

SQL 注入防护

使用参数化查询

// ✓ 安全
$articles = Db::query(
    'SELECT * FROM articles WHERE id = ?',
    [$id]
);

// ✗ 不安全
$articles = Db::query(
    "SELECT * FROM articles WHERE id = {$id}"
);

使用 ORM

// ThinkPHP ORM 自动防注入
$article = Article::where('id', $id)->find();

XSS 防护

输出转义

// 自动转义
{{ $user_input }}

// 不转义(仅用于可信内容)
{!! $trusted_html !!}

内容安全策略(CSP)

在 .htaccess 或 nginx 配置中添加:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';";

CSRF 防护

启用 CSRF 保护

// config/middleware.php
'csrf' => \think\middleware\CheckRequestCache::class,

前端发送 Token

axios.post('/api/articles', data, {
  headers: {
    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
  }
})

文件上传安全

文件类型限制

'upload' => [
    'allowed_types' => ['jpg', 'jpeg', 'png', 'gif', 'pdf'],
    'max_size' => 10 * 1024 * 1024, // 10MB
],

文件名处理

// 重命名文件
$filename = md5(uniqid()) . '.' . $file->extension();

// 存储到安全目录
$file->move(runtime_path() . 'uploads/', $filename);

验证文件内容

// 检查 MIME 类型
$mimeType = $file->getMimeType();
if (!in_array($mimeType, ['image/jpeg', 'image/png'])) {
    throw new Exception('不支持的文件类型');
}

// 检查文件头
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$realMimeType = finfo_file($finfo, $file->getPathname());
finfo_close($finfo);

API 安全

请求频率限制

// 中间件配置
'throttle' => [
    'visit_rate' => '60/m', // 每分钟60次
    'login_rate' => '5/m',  // 登录每分钟5次
],

API 签名验证

function verifySignature($data, $timestamp, $signature) {
    $secret = config('app.api_secret');
    $string = $timestamp . json_encode($data) . $secret;
    $expectedSignature = hash('sha256', $string);

    return hash_equals($expectedSignature, $signature);
}

HTTPS 强制

在 nginx 配置中:

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # SSL 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
}

会话安全

Session 配置

'session' => [
    'secure' => true,      // 仅 HTTPS
    'httponly' => true,    // 防止 JavaScript 访问
    'expire' => 1440,      // 24小时
    'domain' => '',
    'path' => '/',
],

Cookie 安全

setcookie(
    'user_token',
    $token,
    [
        'expires' => time() + 86400,
        'path' => '/',
        'domain' => '',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Strict'
    ]
);

日志与监控

安全日志

记录重要操作:

// 登录日志
Log::info('用户登录', [
    'user_id' => $user->id,
    'ip' => request()->ip(),
    'user_agent' => request()->header('user-agent'),
]);

// 敏感操作日志
Log::warning('删除文章', [
    'article_id' => $id,
    'user_id' => $user->id,
]);

异常监控

// 捕获异常
try {
    // 业务逻辑
} catch (\Exception $e) {
    Log::error('操作失败', [
        'message' => $e->getMessage(),
        'trace' => $e->getTraceAsString(),
    ]);

    // 发送通知
    notify_admin($e);
}

数据库安全

连接安全

# 使用独立数据库账号
DB_USERNAME=cms_user
DB_PASSWORD=strong_password

# 限制权限(仅 SELECT, INSERT, UPDATE, DELETE)

备份策略

# 定时备份
0 2 * * * /usr/bin/mysqldump -u user -p dbname > /backup/db_$(date +\%Y\%m\%d).sql

敏感数据加密

// 加密
$encrypted = encrypt($sensitive_data);

// 解密
$decrypted = decrypt($encrypted);

服务器安全

目录权限

# 设置合适的文件权限
chmod 755 /var/www/cms
chmod 644 /var/www/cms/.env
chmod -R 755 /var/www/cms/runtime

隐藏敏感信息

隐藏 PHP 版本

; php.ini
expose_php = Off

隐藏服务器信息

# nginx.conf
server_tokens off;

防火墙配置

# UFW 示例
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

第三方服务安全

API Key 管理

# 不要在代码中硬编码
OPENAI_API_KEY=sk-xxxxx
QINIU_ACCESS_KEY=xxxxx
QINIU_SECRET_KEY=xxxxx

敏感配置加密

使用环境变量或密钥管理服务。

安全检查清单

部署前检查

  • [ ] 修改默认管理员密码
  • [ ] 配置 HTTPS
  • [ ] 启用 CSRF 保护
  • [ ] 配置文件上传限制
  • [ ] 设置请求频率限制
  • [ ] 配置安全的 Session
  • [ ] 隐藏服务器版本信息
  • [ ] 设置正确的文件权限
  • [ ] 配置数据库备份
  • [ ] 启用日志记录

定期检查

  • [ ] 检查日志中的异常活动
  • [ ] 更新依赖包
  • [ ] 审查用户权限
  • [ ] 检查备份完整性
  • [ ] 扫描安全漏洞
  • [ ] 更新 SSL 证书

应急响应

发现安全问题时

  1. 隔离受影响系统
  2. 分析日志确定影响范围
  3. 修复漏洞
  4. 通知受影响用户
  5. 总结并改进

数据泄露处理

  1. 立即停止泄露
  2. 评估泄露范围
  3. 重置受影响账号密码
  4. 通知用户
  5. 报告相关部门

相关资源

  • OWASP Top 10
  • PHP 安全最佳实践
  • 认证接口
  • 用户管理
在 GitHub 上编辑此页
Prev
日志管理
Next
性能优化