简介
本指南面向DouPHP应用的安全加固,覆盖CSRF防护、XSS防护、SQL注入防护、文件上传安全、数据库安全、网络安全(HTTPS与安全头)、日志审计与安全监控、漏洞扫描与修复流程,以及常见威胁的防护措施和应急响应。内容基于仓库中现有中间件、配置与服务实现进行系统化梳理,并提供可操作的落地建议。
项目结构
DouPHP采用前后端分离的多入口架构(前台 front、后台 admin、API api),通过统一的中间件管道在HTTP边界实施安全策略;安全相关能力集中在以下位置:
- 安全响应头:基类位于 core/foundation/middleware/AbstractSecurityHeadersMiddleware.php,三端各自继承实现。
- CSRF防护:抽象基类位于 core/foundation/middleware/AbstractCsrfMiddleware.php,前台与后台分别实现差异化策略。
- 安全配置:统一在 config/security.php 中定义可信代理、可信Host、安全头、限流与会话Cookie硬化等。
- 会话与令牌:由框架在请求生命周期内处理,结合前端AJAX与表单双提交模式保障一次性令牌安全。
- 文件上传:通过 UploadedFile 与 AttachmentUploadOptions 组合,支持草稿存储、水印、尺寸限制与业务字段标记。
- 数据库安全:使用ORM/查询构建器,配合最小权限账号与参数化查询;部分场景提供安全IN片段构造。
- 密码学:支付插件中可见RSA签名实现,需关注算法强度与密钥管理。
graph TB
Client["客户端"] --> FrontMW["前台中间件<br/>CSRF/安全头/限流"]
Client --> AdminMW["后台中间件<br/>CSRF/安全头/鉴权"]
Client --> ApiMW["API中间件<br/>鉴权/限流/安全头"]
FrontMW --> ControllerF["前台控制器"]
AdminMW --> ControllerA["后台控制器"]
ApiMW --> ControllerApi["API控制器"]
ControllerF --> ServiceF["服务层"]
ControllerA --> ServiceA["服务层"]
ControllerApi --> ServiceApi["服务层"]
ServiceF --> DB["数据库"]
ServiceA --> DB
ServiceApi --> DB
核心组件
- 安全响应头中间件:根据配置下发 X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy,并在HTTPS且开启时下发HSTS。
- CSRF中间件:对POST/PUT/PATCH/DELETE一律校验;对特定GET路由也校验令牌;前台区分一次性令牌与静态令牌,后台统一静态令牌并支持例外路由。
- 安全配置:集中管理可信代理、可信Host、安全头、限流存储与会话Cookie硬化(HttpOnly、Secure、SameSite、Strict模式)。
- 文件上传:通过 UploadedFile 与 AttachmentUploadOptions 封装上传选项(文件名、图片宽度、水印、业务字段、草稿存储等)。
- 数据库安全:ORM/查询构建器默认参数化;部分场景提供安全IN片段构造以防范注入。
- 密码学:支付SDK中使用OpenSSL进行签名,需注意算法强度与密钥保护。
架构总览
下图展示请求进入后,中间件如何串联执行安全策略,包括CSRF校验与安全头下发,以及失败时的拒绝流程。
sequenceDiagram
participant C as "客户端"
participant M as "中间件管道"
participant CSRF as "CSRF中间件"
participant SH as "安全头中间件"
participant Ctrl as "控制器"
participant Svc as "服务层"
participant DB as "数据库"
C->>M : HTTP请求
M->>SH : 前置安全头
SH-->>C : 设置安全响应头
M->>CSRF : 校验CSRF令牌
alt 校验失败
CSRF-->>C : 拒绝重定向或异常
else 校验通过
CSRF->>Ctrl : 继续处理
Ctrl->>Svc : 执行业务逻辑
Svc->>DB : 参数化查询/事务
Svc-->>Ctrl : 返回结果
Ctrl-->>C : 响应
end
详细组件分析
CSRF防护
- 触发条件:所有改写型方法(POST/PUT/PATCH/DELETE)强制校验;特定GET路由(如取消预约、删除收藏)也校验令牌。
- 令牌模型:
- 前台:登录用户共享静态令牌 static_user;匿名表单(注册、登录、找回密码、留言、落地页、分销申请、咨询)使用一次性令牌,防重放。
- 后台:统一静态令牌 static_admin;个别匿名流程(如找回密码提交)使用一次性令牌 password_reset。
- AJAX预检:AJAX走“仅校验不消费”,原生表单再走“校验+消费”,兼容双提交模式。
- 豁免名单:外部回调(支付/微信)通过路由级声明式豁免,避免硬编码名单。
- 拒绝行为:前台抛异常并重定向首页;后台抛异常并显示统一提示页。
flowchart TD
Start(["进入CSRF中间件"]) --> Method{"是否改写型方法?"}
Method -- 是 --> Verify["读取token并校验(verify/check)"]
Method -- 否 --> CheckRoute{"是否GET-token路由?"}
CheckRoute -- 是 --> Verify
CheckRoute -- 否 --> Pass["放行"]
Verify --> Ok{"校验通过?"}
Ok -- 否 --> Reject["拒绝并返回错误"]
Ok -- 是 --> Next["继续下游处理"]
Reject --> End(["结束"])
Next --> End
安全响应头与网络安全
- 基线安全头:X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy,按配置下发。
- HSTS:仅在HTTPS且配置启用时下发,支持max-age与includeSubDomains。
- 可信代理与Host:trusted_proxies与trusted_hosts用于正确识别真实IP与Host,防止伪造Host污染对外链接。
- 会话Cookie硬化:HttpOnly、Secure、SameSite、Strict模式,降低XSS窃取与跨站风险。
classDiagram
class AbstractSecurityHeadersMiddleware {
+handle(next) mixed
-sendHeaders(headers) void
}
class Config {
+get(key, default) mixed
}
AbstractSecurityHeadersMiddleware --> Config : "读取security.headers"
文件上传安全
- 上传入口:前台用户控制器将$_FILES包装为UploadedFile,并通过AttachmentUploadOptions设置上传选项(文件名、图片宽度、水印、业务字段、草稿存储)。
- 安全要点:
- 类型验证:在服务层或存储层依据业务白名单校验MIME/扩展名。
- 大小限制:结合服务器与业务配置限制最大文件大小。
- 路径遍历防护:使用随机文件名与固定目录,禁止直接拼接用户输入路径。
- 草稿机制:支持暂存与审核后再落库,便于二次校验。
- 水印与尺寸:统一处理图片尺寸与水印,减少恶意资源影响。
sequenceDiagram
participant U as "用户"
participant C as "前台控制器"
participant UF as "UploadedFile"
participant AO as "AttachmentUploadOptions"
participant AS as "附件服务"
U->>C : 提交表单(含文件)
C->>UF : 从全局获取文件
C->>AO : 设置选项(文件名/尺寸/水印/业务字段)
C->>AS : 存储(草稿/正式)
AS-->>U : 返回URL/状态
数据库安全与SQL注入防护
- 参数化查询:优先使用ORM/查询构建器,避免字符串拼接。
- 安全IN片段:当必须拼接IN子句时,使用安全函数将所有值转为整数后拼接,防止注入。
- 最小权限:数据库账号仅授予必要权限,避免使用高权限账户。
- 敏感数据加密:密码重置令牌使用哈希存储,避免明文传输/存储。
flowchart TD
A["接收ID列表"] --> B["intval转换每个元素"]
B --> C["implode生成安全IN片段"]
C --> D["拼接到查询语句"]
D --> E["执行查询"]
密码学与密钥管理
- 密码重置:使用随机字节生成令牌,并以SHA-256哈希存储,避免明文泄露。
- 支付签名:支付SDK使用OpenSSL进行签名,注意算法强度(优先SHA-256)与私钥保护。
- 应用密钥:应用密钥应妥善管理,避免硬编码到代码仓库。
sequenceDiagram
participant U as "用户"
participant S as "密码重置服务"
participant DB as "数据库"
U->>S : 请求重置密码
S->>S : 生成随机令牌
S->>S : 计算令牌哈希
S->>DB : 保存哈希与过期时间
S-->>U : 返回令牌(仅一次)
依赖关系分析
- 中间件依赖:CSRF与安全头中间件均依赖配置中心读取安全策略,并在请求生命周期早期生效。
- 控制器与服务:控制器负责组装请求与调用服务;服务层封装业务逻辑与数据安全操作。
- 外部依赖:支付SDK依赖OpenSSL进行签名,需确保环境启用相应扩展并使用强算法。
graph LR
Config["安全配置"] --> CSRF["CSRF中间件"]
Config --> SH["安全头中间件"]
CSRF --> Ctrl["控制器"]
SH --> Ctrl
Ctrl --> Svc["服务层"]
Svc --> DB["数据库"]
Svc --> Pay["支付SDK"]
性能与安全权衡
- CSRF校验开销:中间件层轻量校验,对性能影响极小;一次性令牌防重放提升安全性。
- 安全头下发:仅在命中路由时下发,避免404等非路由场景的性能损耗。
- 文件上传:草稿机制允许二次校验,可能增加I/O,但显著提升安全性。
- 数据库安全:参数化查询与最小权限策略对性能影响有限,但能显著降低注入风险。
故障排查指南
- CSRF失败:检查表单是否包含正确令牌;确认AJAX预检未消费一次性令牌;核对豁免路由配置。
- 安全头缺失:确认中间件已挂载至管道;检查配置项是否启用;确认HTTPS环境下HSTS开关。
- 上传失败:检查类型白名单与大小限制;确认草稿存储路径可写;核对业务字段与水印配置。
- 数据库错误:检查参数化查询是否正确;确认IN片段安全构造;核对数据库账号权限。
- 支付签名异常:确认OpenSSL扩展启用;核对算法与密钥格式;检查私钥保护与权限。
结论
DouPHP在HTTP边界提供了完善的CSRF与安全头中间件,结合集中化的安全配置与会话硬化,能够有效抵御常见Web攻击。文件上传与数据库访问通过服务层与工具函数强化安全控制。建议在部署时严格配置可信代理与Host、启用HTTPS与安全头、最小化数据库权限,并定期扫描与修复漏洞,建立完整的日志审计与应急响应流程。
附录:配置与操作清单
- 网络安全
- 启用HTTPS并配置HSTS(max-age与includeSubDomains按需开启)。
- 配置可信代理与可信Host,防止IP与Host伪造。
- 下发安全头:X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy。
- CSRF防护
- 前台:为匿名表单生成一次性令牌;登录用户表单使用静态令牌。
- 后台:统一静态令牌;必要时为匿名流程配置一次性令牌。
- 豁免外部回调路由,避免误拦截。
- 文件上传
- 服务端校验文件类型白名单与大小限制。
- 使用随机文件名与固定目录,禁止拼接用户输入路径。
- 启用草稿机制,二次校验后再落库。
- 数据库安全
- 使用参数化查询;必要时使用安全IN片段构造。
- 数据库账号最小权限;禁用高危功能。
- 敏感数据(如令牌)哈希存储,避免明文。
- 密码学与密钥
- 优先使用强算法(如SHA-256);妥善保管私钥与应用密钥。
- 定期检查支付SDK的算法与密钥配置。
- 日志审计与监控
- 记录关键操作(登录、上传、导出、备份)与异常事件。
- 集中日志收集与分析,设置告警阈值。
- 漏洞扫描与修复
- 定期使用静态/动态扫描工具检测漏洞。
- 建立修复优先级与回滚策略,及时更新依赖。