实测 Flask session cookie 的安全相关配置:默认只有 HttpOnly 没有 Secure 与 SameSite、每个配置项对应的 Set-Cookie 属性(含 __Host- 前缀与 Partitioned)、permanent 的 Expires、REFRESH_EACH_REQUEST 的续期与 Vary: Cookie、cookie 超过约 4093 字节时的警告、test client 不执行 Secure 规则。
用真实的无头 Chrome 验证 HttpOnly、Secure、SameSite:HttpOnly 让 JS 读不到 document.cookie 但不影响请求、没写 SameSite 时 Chrome 按 Lax 处理、Lax 与 Strict 都挡住跨站子请求、SameSite=None 没有 Secure 时 cookie 被浏览器拒绝、None 加 Secure 才能跨站带 cookie。
在真实的 Chrome 里复现 CSRF:恶意页面(跨站)自动提交 POST 表单转走受害者的钱,显式 Lax 能挡住但没写 SameSite 的 cookie 挡不住、GET 形式的转账接口 Lax 也挡不住、SameSite=None 时必须靠 CSRFProtect(缺 token 得到 400)、CSRFProtect 不检查 GET。
在真实的 Chrome 里验证 Flask/Jinja2 的 XSS 防护:自动转义挡住正文里的 script、|safe 与 Markup 误用让攻击执行、不加引号的属性被注入、JS 里没有引号的位置 HTML 转义无效而 |tojson 安全、href 里的 javascript: 协议不被转义拦截。
从防御角度实测参数化查询:带单引号的正常名字在字符串拼接下语法错误而绑定参数正常;ORM 表达式自动生成占位符;列名与排序用白名单;LIKE 的通配符用 autoescape;PostgreSQL 服务端日志里语句以 $1 占位符执行。
实测 Flask 安全地提供文件下载:send_from_directory 对各种文件名的结果、safe_join 的返回值、符号链接指向目录外时不会被拦、Content-Disposition 的中文文件名、Range 与条件请求内置支持、secure_filename 会丢掉非 ASCII 字符。
实测 Flask 文件上传的类型校验:只看扩展名与客户端声明的 Content-Type 会被纯文本冒充、校验文件头签名加扩展名一致加 Pillow 解析能挡住冒充与垃圾、保存时用随机 uuid 名字、对 secure_filename 的结果取扩展名会误拒中文文件名、MAX_CONTENT_LENGTH 返回 413、被截断的 PNG 要靠解析才能发现。
实测 Flask 的 Host 头校验:默认接受任何 Host 且 url_for(_external=True) 随 Host 变化、TRUSTED_HOSTS 只接受名单(含 .example.org 子域写法)否则 400、SERVER_NAME 固定外部链接但不拒绝请求、用固定基地址生成邮件链接、X-Forwarded-Host 只在 ProxyFix(x_host=1) 时生效、真实 gunicorn 上的结果。
从防御角度检查 CORS 配置的安全边界:默认与 "*" 加 credentials 会回显任意 Origin(含 null)、明确名单只放行自己的前端、正则匹配 origins 不转义不锚定时别人的域名也能通过、CORS 不是认证、Vary: Origin、用 resources 与 methods 限定路径与方法。
实测登录接口的限流设计:不管成败都计数会挡住正常用户、deduct_when 只计失败、按用户名限流能挡住换 IP 的猜测但会让账号被人为锁住、用户名层加 IP 层两层叠加、限流在密码校验之前生效、配置在 Limiter 初始化之后设置不生效所以 429 没有 Retry-After。
实测 Werkzeug 密码哈希:默认 scrypt 的格式与随机盐、各方法单次耗时(sha256 一次 0.001 ms 对 scrypt 66 ms 对 argon2id 30 ms)、登录成功时把旧的弱哈希升级写回、参数写在哈希里旧哈希仍可验证、超长密码、argon2-cffi 的 check_needs_rehash。
实测登录失败锁定的设计细节:失败 5 次后锁定一段时间、锁定期间正确密码也被拒、成功登录清零;用统一响应避免枚举账号;不存在的用户也做一次假哈希把响应时间差从 66 ms 压到 0.3 ms;并发下非原子计数 20 次全部放行而原子 UPDATE 只放行 5 次。