安全与限流
深度/复杂度限制、鉴权、勿暴露内省于生产。
25 分钟
安全与限流
GraphQL 单端点 放大攻击面:恶意 Query 可请求极深嵌套、超大列表,耗尽 CPU/数据库。REST /tracks 路径固定相对可预测;GraphQL 需 深度、复杂度、速率 多层防护。
学习目标
- 配置查询深度与复杂度上限
- 在 Resolver 层做鉴权,不依赖 Schema 隐藏
- 对齐 spring-boot-essentials 安全实践
核心内容
典型威胁
# 深度攻击示例(勿对生产执行)
query Evil {
tracks {
lessons {
track {
lessons {
track { slug }
}
}
}
}
}
循环引用类型 + 无限制深度 → 栈/查询爆炸。另:批量 alias 可放大单次请求成本。
深度与复杂度限制
Spring GraphQL 可注册 GraphQlSourceBuilderCustomizer 或使用社区 instrumentation:
// 概念:拒绝 depth > 10 或 complexity > 500 的查询
@Component
public class MaxDepthInstrumentation implements Instrumentation {
private static final int MAX_DEPTH = 8;
// 在 execution 前计算深度,超限抛 GraphQLException
}
网关层(Nginx、API Gateway)对 /graphql 单独限流,严于 REST 列表接口。
鉴权
@QueryMapping
@PreAuthorize("hasRole('ADMIN')")
public List<Track> tracks() { ... }
- Query 字段级:
@PreAuthorize或自定义DataFetcherExceptionResolver - 与 JWT 过滤器共用 SecurityContext(sb-jwt)
- Introspection 仅 ADMIN 或开发 profile
字段返回 null ≠ 无权限;敏感字段应 拒绝 并记录审计。
生产清单
| 项 | 建议 |
|---|---|
| GraphiQL | 仅 dev/staging |
| Introspection | 生产关闭或需 token |
| 持久化 Query | 可选,只允许白名单 operationId |
| 日志 | 记录 operationName、耗时、拒绝原因 |
| 错误信息 | 不泄露 SQL/堆栈 |
本站 主 API REST 已走 HTTPS + JWT;实验 GraphQL 不得公网裸奔。mongodb-essentials 经 Resolver 暴露时须参数绑定,防注入。
练习
- 列出 3 条 GraphQL 特有、REST 较少见的安全项