先说结论
面向企业的系统,安全不是"加个验证码",是四层默认值:密码存储、请求校验、输出净化、行为审计。
第一层:密码
- 用 Argon2id(PHP 原生支持)
- 不存明文、不存 MD5/SHA1
- 登录失败限流(按 IP + 账号)
- 会话 ID 登录后重新生成
第二层:请求校验
- 全站 CSRF token(表单 + AJAX)
- 写操作只接受 POST
- 文件上传校验类型与大小,重命名存储
- 上传目录禁止执行脚本
第三层:输出净化
- 富文本走白名单(允许的标签与属性固定)
- Markdown 渲染关闭原始 HTML(
html_input: strip) - 所有输出到 HTML 的变量做转义
- JSON-LD 用
JSON_HEX_TAG等标志防注入
第四层:审计
- 登录记录:时间、IP、结果
- 内容操作:谁在什么时候改了什么
- API 调用:端点、结果、耗时
审计日志的价值不在"防",在"出事能查"。
一个容易被忽略的点
JSON-LD 注入。把用户输入拼进 <script type="application/ld+json"> 时,如果内容里有 </script>,就能逃逸出来执行脚本。
解法:json_encode(..., JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT)。
上线前的安全动作
- 改掉默认后台路径
- 管理员密码 16 位以上
- 关掉错误显示(生产环境)
- 数据库只监听本地
- 定期备份并验证能恢复
实际修过三类问题:JSON-LD 没转义导致脚本逃逸、上传目录可执行 PHP、一个忘记加 CSRF 的 AJAX 端点。测试主要靠自查清单 + composer audit,没做过正式渗透测试。