简介
本方案围绕 DouPHP 的敏感数据保护,覆盖密码哈希与盐值、传输层安全(HTTPS/TLS/安全头)、静态数据加密(数据库字段、配置文件、文件存储)、API 接口安全(请求签名与响应脱敏)以及密钥管理与轮换策略。文档同时给出性能优化与兼容性建议,帮助在生产环境安全落地。
项目结构
与安全相关的关键位置:
- 安全配置与中间件:config/security.php、各端 SecurityHeadersMiddleware、AbstractSecurityHeadersMiddleware
- 密码与令牌:front/facade/Auth.php、core/service/user/ApiTokenService.php、UserAuthService
- 静态数据加密:core/service/ai/CredentialCipher.php、admin/model/ai/AiKey.php
- 第三方集成签名与 TLS:alipay SDK、SMTP TLS
- 应用密钥:config/config.php 中的 DOU_APP_KEY
graph TB
A["安全配置<br/>config/security.php"] --> B["安全响应头中间件<br/>AbstractSecurityHeadersMiddleware"]
C["密码校验与升级<br/>front/facade/Auth.php"] --> D["API Token服务<br/>ApiTokenService"]
E["AI凭据加密器<br/>CredentialCipher"] --> F["AI Key模型<br/>AiKey.php"]
G["应用密钥<br/>DOU_APP_KEY"] --> E
H["第三方签名/TLS<br/>支付宝/微信/SMTP"] --> I["业务调用方"]
图表来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- front/facade/Auth.php:612-633
- core/service/user/ApiTokenService.php:42-158
- core/service/ai/CredentialCipher.php:23-344
- admin/model/ai/AiKey.php:67-83
- config/config.php:48-50
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
- core/library/mail/src/Smtp.php:329-348
章节来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- config/config.php:48-50
核心组件
- 密码哈希与迁移:前端登录流程在检测到历史 MD5 时自动升级为 bcrypt,并持久化新哈希;验证统一使用 password_verify。
- API 令牌:签发不透明随机 token,库内仅存 sha256(token),支持过期、按设备吊销与全量吊销。
- 静态数据加密:AI 凭据通过 AES-256-CBC + HMAC-SHA256 进行加密封装,支持旧密钥重包与兼容读取。
- 传输安全:安全头中间件下发基线安全头与可选 HSTS;邮件发送启用 STARTTLS;第三方支付 SDK 使用 RSA/RSA2 签名。
- 密钥管理:站点级 DOU_APP_KEY 用于派生对称密钥;必要时回退到 DOU_SHELL;提供重包工具以平滑轮换。
章节来源
- front/facade/Auth.php:612-633
- core/service/user/ApiTokenService.php:42-158
- core/service/ai/CredentialCipher.php:23-344
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- core/library/mail/src/Smtp.php:329-348
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
架构总览
下图展示从请求进入、安全头下发、认证鉴权、令牌签发与静态数据加密的整体链路。
sequenceDiagram
participant Client as "客户端"
participant MW as "安全头中间件"
participant Auth as "认证/授权"
participant Token as "ApiTokenService"
participant DB as "数据库"
participant Enc as "CredentialCipher"
Client->>MW : HTTP 请求
MW-->>Client : 安全头X-Frame-Options/Referrer-Policy/HSTS等
MW->>Auth : 路由处理
Auth->>Token : 签发/解析 token
Token->>DB : 写入/查询 token_hash
DB-->>Token : 行记录
Token-->>Auth : 用户上下文
Auth->>Enc : 读写 AI 凭据可选
Enc->>DB : 存取密文
DB-->>Enc : 密文
Enc-->>Auth : 明文凭据
Auth-->>Client : 响应已脱敏
图表来源
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- core/service/user/ApiTokenService.php:57-124
- core/service/ai/CredentialCipher.php:95-192
- admin/model/ai/AiKey.php:67-83
详细组件分析
密码哈希与盐值机制
- 算法选择:优先使用 bcrypt;对历史 MD5 在登录时自动升级。
- 盐值:由框架内置函数生成与管理,无需手动维护。
- 实现要点:
- 检测历史 MD5 长度与格式,匹配则用 bcrypt 重新哈希并更新。
- 验证统一走 password_verify,避免自定义散列逻辑。
flowchart TD
Start(["登录入口"]) --> CheckPwd["读取库内密码哈希"]
CheckPwd --> IsMD5{"是否为历史MD5?"}
IsMD5 -- 是 --> Upgrade["使用bcrypt重新哈希并保存"]
IsMD5 -- 否 --> Verify["password_verify验证"]
Upgrade --> Verify
Verify --> Result{"验证通过?"}
Result -- 否 --> Fail["记录失败审计/限流"]
Result -- 是 --> Success["建立会话/签发token"]
图表来源
- front/facade/Auth.php:612-633
章节来源
- front/facade/Auth.php:612-633
API 令牌与请求签名
- 令牌签发:生成 64 字符十六进制随机串(CSPRNG),库内仅存 sha256(token),带过期时间。
- 令牌解析:正则校验格式 → 计算 hash → 精确匹配 → 清理过期行 → 心跳刷新 last_active。
- 吊销能力:单 token 吊销与按用户全量吊销。
- 请求签名:第三方对接(如支付宝)采用 RSA/RSA2 签名,确保请求完整性与抗重放。
sequenceDiagram
participant App as "业务模块"
participant Token as "ApiTokenService"
participant DB as "数据库"
participant Third as "第三方服务"
App->>Token : issue(userId, ip)
Token->>DB : 插入 token_hash + 过期时间
DB-->>Token : 成功
Token-->>App : 返回明文token(仅一次)
App->>Third : 构造请求+RSA签名
Third-->>App : 验签结果
App->>Token : resolve(token)
Token->>DB : 查找并校验hash_equals
DB-->>Token : 命中/未命中
Token-->>App : userId或0
图表来源
- core/service/user/ApiTokenService.php:57-158
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
章节来源
- core/service/user/ApiTokenService.php:57-158
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
静态数据加密(数据库字段、配置文件、文件存储)
- 数据库字段加密:AI 凭据通过 CredentialCipher 进行 AES-256-CBC + HMAC-SHA256 封装,落库前校验长度上限,读取时兼容旧密钥并重包。
- 配置文件加密:敏感配置(如第三方密钥)应通过相同加密器封装后存储,并在模型属性访问器中透明加解密。
- 文件存储加密:大文件或敏感附件建议使用服务端加密存储(如对象存储 SSE),或在入库前经加密通道上传;当前仓库未提供通用文件加密器,可按需扩展。
classDiagram
class CredentialCipher {
+encrypt(plaintext) string
+encryptForStorage(plaintext,maxBytes) string
+decrypt(stored) string
+rewrapIfNeeded(stored,maxBytes) string
+isEncrypted(stored) bool
-deriveKey(secret) string
-parsePayload(stored) array|null
-macMatches(parts,key) bool
-opensslDecrypt(parts,key) string
}
class AiKey {
+setConfigAttribute(value) string
+getConfigAttribute(value) string
}
AiKey --> CredentialCipher : "使用"
图表来源
- core/service/ai/CredentialCipher.php:95-344
- admin/model/ai/AiKey.php:67-83
章节来源
- core/service/ai/CredentialCipher.php:95-344
- admin/model/ai/AiKey.php:67-83
数据传输加密(HTTPS、TLS、安全头)
- HTTPS 强制与 HSTS:通过 config/security.php 的 headers.hsts 控制仅在 HTTPS 且开启时下发 Strict-Transport-Security;生产建议启用并设置合理 max_age。
- 安全头:X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy 由中间件统一下发。
- TLS:邮件发送使用 STARTTLS 建立加密通道;第三方支付 SDK 使用 OpenSSL 进行签名。
flowchart TD
Req["HTTP请求"] --> CheckHSTS{"是否HTTPS且启用HSTS?"}
CheckHSTS -- 是 --> SetHSTS["下发HSTS头"]
CheckHSTS -- 否 --> SkipHSTS["跳过HSTS"]
SetHSTS --> Headers["下发其他安全头"]
SkipHSTS --> Headers
Headers --> Next["继续路由处理"]
图表来源
- config/security.php:62-72
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- core/library/mail/src/Smtp.php:329-348
章节来源
- config/security.php:62-72
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- core/library/mail/src/Smtp.php:329-348
API 接口安全传输(请求签名与响应脱敏)
- 请求签名:对接第三方(如支付宝)时使用 RSA/RSA2 签名,保证请求不可篡改与来源可信。
- 响应脱敏:对外 JSON 响应应避免返回敏感字段(如完整 token、内部 ID、密钥片段),可在服务层统一过滤后再输出。
- 微信回调签名:公众号回调使用 token、timestamp、nonce 进行 SHA1 校验,防止伪造请求。
sequenceDiagram
participant Client as "客户端"
participant API as "API控制器"
participant Sign as "签名校验"
participant Resp as "响应构建"
Client->>API : 携带签名参数
API->>Sign : 校验签名
Sign-->>API : 通过/拒绝
API->>Resp : 构建响应脱敏
Resp-->>Client : 安全响应体
图表来源
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
- core/service/weixin/WeixinService.php:39-65
章节来源
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
- core/service/weixin/WeixinService.php:39-65
密钥管理系统与轮换策略
- 密钥来源:优先使用 DOU_APP_KEY;若缺失则回退到 DOU_SHELL;两者均不存在将抛出异常。
- 密钥派生:通过对站点密钥进行固定前缀的哈希派生出对称密钥,避免直接使用原始密钥。
- 轮换策略:
- 新增 DOU_APP_KEY 后,使用 rewrapStoredCredentials 对存量凭据进行重包,使密文绑定新密钥。
- 保留 legacyKey 以兼容旧密文读取,直至全部迁移完成。
- 定期评估密钥强度与生命周期,结合外部 KMS(如云KMS/HSM)实现集中化管理与自动轮换。
flowchart TD
Start(["启动/初始化"]) --> LoadKey["加载DOU_APP_KEY/DOU_SHELL"]
LoadKey --> Derive["派生对称密钥"]
Derive --> Encrypt["加密凭据/配置"]
Encrypt --> Store["落库/存储"]
Store --> Rotate{"需要轮换?"}
Rotate -- 是 --> Rewrap["重包存量密文到新密钥"]
Rotate -- 否 --> End(["结束"])
Rewrap --> End
图表来源
- core/service/ai/CredentialCipher.php:197-263
- core/service/ai/CredentialCipher.php:60-89
- config/config.php:48-50
章节来源
- core/service/ai/CredentialCipher.php:60-89
- core/service/ai/CredentialCipher.php:197-263
- config/config.php:48-50
依赖关系分析
- 安全头中间件依赖安全配置;认证流程依赖密码哈希与令牌服务;静态加密依赖应用密钥;第三方集成依赖 OpenSSL 与签名算法。
- 潜在耦合点:
- 若禁用 OpenSSL,静态加密将无法工作。
- 若未正确配置 HSTS,可能导致降级攻击风险。
- 若第三方签名算法不匹配,会导致验签失败。
graph LR
SecCfg["安全配置"] --> SecMW["安全头中间件"]
Auth["认证流程"] --> Pwd["密码哈希"]
Auth --> Token["令牌服务"]
Token --> DB["数据库"]
Enc["静态加密"] --> Key["应用密钥"]
Third["第三方集成"] --> SSL["OpenSSL/签名"]
图表来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- front/facade/Auth.php:612-633
- core/service/user/ApiTokenService.php:57-124
- core/service/ai/CredentialCipher.php:107-119
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
章节来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- front/facade/Auth.php:612-633
- core/service/user/ApiTokenService.php:57-124
- core/service/ai/CredentialCipher.php:107-119
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
性能考虑
- 密码哈希:bcrypt 默认成本较高,可根据服务器负载调整成本因子;登录路径存在自动升级,注意批量导入时预哈希以减少在线开销。
- 令牌解析:使用正则与 hash_equals 恒定时间比较,减少时序攻击风险;心跳刷新限制为每分钟一次,降低写放大。
- 静态加密:AES-256-CBC + HMAC 计算开销可控;对高频读场景可引入内存缓存(注意缓存键与密钥版本)。
- 传输层:HSTS 可减少首程降级风险;STARTTLS 在邮件发送中按需启用,避免不必要的握手开销。
故障排查指南
- 无法加密/解密 AI 凭据:检查 OpenSSL 扩展是否启用;确认 DOU_APP_KEY/DOU_SHELL 已定义且非空;查看异常信息定位 MAC 校验失败或解密失败。
- HSTS 未生效:确认当前请求为 HTTPS 且 security.headers.hsts.enabled 为 true;检查中间件是否在管道前置执行。
- 第三方签名失败:核对 sign_type(RSA/RSA2)与私钥/公钥配置;确保参数排序与编码一致。
- 邮件 TLS 失败:检查 SMTP 服务器是否支持 STARTTLS;确认证书链与协议版本兼容。
章节来源
- core/service/ai/CredentialCipher.php:107-119
- core/service/ai/CredentialCipher.php:177-192
- config/security.php:62-72
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:35-49
- plugin/alipayf2f/sdk/aop/AlipayMobilePublicMultiMediaClient.php:153-180
- core/library/mail/src/Smtp.php:329-348
结论
DouPHP 已在密码哈希、API 令牌、静态数据加密与传输安全方面形成闭环:密码采用 bcrypt 并自动升级;API 令牌以哈希形式存储并支持吊销;AI 凭据通过 AES-256-CBC + HMAC 安全封装,支持密钥轮换;安全头与 HSTS 提供基线防护,邮件与第三方集成启用 TLS/签名。建议在生产环境启用 HSTS、强化密钥管理(结合外部 KMS)、并对高敏感数据实施更细粒度的加密与访问控制。
附录
- 关键配置项说明:
- security.headers:安全头集合,含 HSTS 开关与策略。
- security.session:会话 Cookie 硬化选项(httponly、secure、samesite、use_strict_mode)。
- DOU_APP_KEY:应用密钥,用于派生对称密钥。
- 推荐实践:
- 全站 HTTPS 并启用 HSTS。
- 所有敏感配置与凭据通过加密器存储,禁止明文落库。
- 对外响应统一脱敏,避免泄露敏感字段。
- 定期轮换密钥并执行重包任务,确保存量数据绑定新密钥。
章节来源
- config/security.php:51-86
- config/config.php:48-50
- core/service/ai/CredentialCipher.php:60-89