安全总览
数据墙DBW 通过 REST、GraphQL 和 MCP 端点对外暴露数据,安全性是其核心设计考量之一。安全模型分为五个相互关联的层次,共同构成纵深防御体系。
安全模型概览
请求 → 传输安全(TLS)
→ 身份验证(谁在调用?)
→ 授权(能做什么?)
→ 实体级权限(哪些实体和操作?)
→ 字段级控制(哪些列?)
→ 行级过滤(哪些数据行?)
→ 数据库执行每一层独立配置又层层递进。未显式授予的访问一律拒绝——这是数据墙DBW 安全模型的基本原则。
第一层:传输安全
传输安全保护客户端与服务端之间的数据不被窃听或篡改。
| 要求 | 说明 |
|---|---|
| 启用 TLS | 生产环境必须使用 HTTPS,禁止通过未加密 HTTP 暴露服务 |
| TLS 1.2+ | 禁用旧版 TLS 协议,仅依赖 TLS 1.2 及以上版本 |
| 证书管理 | 使用受信任 CA 签发的证书,开发环境可通过反向代理终止 TLS |
数据墙DBW 本身不直接处理 TLS 终止——推荐在服务前放置反向代理(Nginx、Traefik)或 API 网关,由代理处理 HTTPS 并将请求以 HTTP 转发给数据墙DBW。这既简化了证书管理,也便于统一日志和访问控制。
第二层:身份验证
身份验证确认请求的来源身份——调用方是谁。
验证方式
| 方式 | 配置值 | 适用场景 |
|---|---|---|
| JWT Bearer 令牌验证 | Custom | 引擎自行验证 JWT 令牌的 issuer、audience 和签名。角色必须位于 roles 声明中(固定,不可配置) |
| 信任网关注入的身份 | Unauthenticated | 网关已完成认证,引擎信任请求头中的身份信息。所有请求以 anonymous 角色运行 |
| 开发模拟 | Simulator | 本地开发和测试,跳过外部验证。仅限开发模式,生产环境会拒绝启动 |
身份验证流程
1. 客户端获取令牌(JWT 方式)或由网关注入身份头
2. 请求携带 Authorization: Bearer <token> 或平台身份标头
3. 数据墙DBW 验证令牌签名、issuer、audience(JWT 模式)
或信任网关注入的身份信息(Unauthenticated 模式)
4. 从令牌的 roles 声明或身份头中提取用户角色
5. 身份信息传递给授权层进行权限判断快速配置
{
"runtime": {
"host": {
"authentication": {
"provider": "Custom",
"jwt": {
"issuer": "https://identity.example.com/",
"audience": "api://dab-api"
}
}
}
}
}配置项:
| 字段 | 说明 |
|---|---|
provider | Unauthenticated、Custom 或 Simulator |
jwt.issuer | JWT 令牌的签发方,引擎验证令牌中的 iss 声明是否匹配 |
jwt.audience | 预期的接收方标识,引擎验证令牌中的 aud 声明是否匹配 |
第三层:授权(RBAC)
授权决定通过验证的用户能做什么操作。数据墙DBW 使用基于角色的访问控制模型。
角色体系
| 角色类型 | 角色 | 分配方式 |
|---|---|---|
| 系统角色 | Anonymous | 请求中无有效身份信息时自动分配 |
| 系统角色 | Authenticated | 请求通过身份验证但未指定具体角色时自动分配 |
| 用户角色 | 自定义 | 来自 JWT 令牌的 roles 声明,通过 X-MS-API-ROLE 请求头选择 |
每次请求只在一个最终生效角色的上下文中评估。角色判定逻辑如下:
| Bearer Token | X-MS-API-ROLE | 最终角色 |
|---|---|---|
| 无 | — | Anonymous |
| 有效 | 无 | Authenticated(即使令牌包含多个角色,未指定时仍使用此角色) |
| 有效 | 有,且令牌包含该角色 | 指定角色 |
| 有效 | 有,但令牌不包含该角色 | 拒绝(403) |
| 无效 | — | 拒绝(401) |
NOTE
一个请求的已验证主体可能关联多个角色。然而,数据墙DBW在计算权限与策略时,始终只针对一个最终生效角色进行评估。当提供了 X-MS-API-ROLE 标头时,它会决定此次请求使用哪个角色。
实体权限
权限在实体级别配置,描述"哪个角色能对这个实体执行哪些操作":
{
"Book": {
"permissions": [
{ "role": "anonymous", "actions": ["read"] },
{ "role": "authenticated", "actions": ["read", "create"] },
{ "role": "editor", "actions": ["read", "create", "update"] },
{ "role": "admin", "actions": ["*"] }
]
}
}操作类型:
| 操作 | 适用对象 | 含义 |
|---|---|---|
read | 表、视图 | 查询数据 |
create | 表 | 插入记录(视图不支持 create) |
update | 表、视图 | 修改记录 |
delete | 表、视图 | 删除记录 |
execute | 存储过程 | 执行存储过程 |
* | 全部 | 通配符,等于该类型支持的全部操作 |
默认拒绝原则
未配置 permissions 的实体拒绝所有访问。未在配置中引用的数据库对象不会暴露在 API 中。这确保了"看不到的就是访问不到的"。
角色继承
NOTE
角色继承是数据墙DBW 2.0 预览版功能,正式发布前可能会发生变化。
链式继承减少重复配置:自定义角色 → authenticated → anonymous。未显式配置的角色自动沿用下一级角色的权限。在 anonymous 上配置一次 read,authenticated 和所有未配置的命名角色自动拥有读取权限。
你可以通过 dab configure --show-effective-permissions 查看继承应用后的最终解析权限。
第四层:细粒度访问控制
在实体操作权限的基础上,可以进一步精确到列和行。
字段级控制
按角色控制每个操作可访问的字段:
{
"role": "auditor",
"actions": [
{
"action": "read",
"fields": {
"include": ["*"],
"exclude": ["salary", "password_hash"]
}
}
]
}被排除的字段对所有协议(REST、GraphQL、MCP)生效,客户端引用被禁字段时收到拒绝响应。
行级安全(数据库策略)
通过 OData 风格表达式在数据库查询中追加 WHERE 条件:
{
"action": "read",
"policy": {
"database": "@item.ownerId eq @claims.userId"
}
}语法要素:
| 要素 | 含义 | 示例 |
|---|---|---|
@item.<field> | 引用实体的字段值(使用映射后的 API 字段名) | @item.ownerId |
@claims.<claim> | 引用 JWT 令牌中的声明值 | @claims.userId |
| 比较运算 | eq(相等)、ne(不等)、gt、ge、lt、le | @item.price lt 100 |
| 逻辑运算 | and、or | @item.active eq true and @item.published eq true |
WARNING
如果策略中引用的声明不存在于令牌中,请求会以 403 Forbidden 被拒绝。请确保身份提供程序输出了所有必需声明。
策略适用于 read、update、delete 操作。create 和 execute 不支持策略(INSERT 语句不支持 WHERE 谓词,存储过程不接受查询谓词)。不同数据库对策略语法的支持一致,底层被转换为各数据库的原生查询谓词。
NOTE
文档数据库场景当前不支持数据库策略。完整语法参考请参阅数据库策略。
会话上下文(仅 SQL Server 2016+)
IMPORTANT
SQL Server 行级安全中的 session context 与数据墙DBW数据库策略不同。数据库策略会被数据墙DBW转换成 WHERE 子句;而 session context 则是把 JWT 声明转发给 SQL Server,再由 SQL Server 原生的行级安全机制负责过滤。
启用 set-session-context 后,引擎将 JWT 声明注入 SQL Server 的 SESSION_CONTEXT:
{
"data-source": {
"options": {
"set-session-context": true
}
}
}声明通过 SESSION_CONTEXT(N'key') 在数据库内部访问,可用于存储过程、触发器和视图中的自定义权限逻辑。
WARNING
启用 set-session-context 后,该数据源的响应缓存会被禁用。对于高流量场景,请考虑做性能测试、为谓词列建立索引,或者在满足需求时改用数据墙DBW数据库策略。
注意:会话上下文启用后,不同用户的缓存结果不能共享,需调整缓存策略。
第五层:配置安全
安全不仅是运行时的访问控制,配置本身也需要被保护。
密钥管理
永远不在配置文件中写入明文密码,使用 @env() 引用环境变量:
{
"data-source": {
"connection-string": "@env('SQL_CONNECTION_STRING')"
}
}启动前通过系统环境变量、.env 文件(仅开发环境)或容器环境变量注入实际值。.env 文件和包含密钥的环境配置文件必须加入 .gitignore。
生产环境配置
{
"runtime": {
"host": {
"mode": "production",
"cors": {
"origins": ["https://app.example.com"],
"allow-credentials": false
}
},
"graphql": { "allow-introspection": false }
}
}| 配置 | 生产建议 | 原因 |
|---|---|---|
host.mode | production | 禁用 Swagger UI、详细错误堆栈和调试信息 |
graphql.allow-introspection | false(默认为 true) | 防止外部探测完整的 API 架构 |
cors.origins | 精确指定域名,不使用 "*" | 限制跨域访问来源 |
| 日志级别 | Warning 或 Error | 减少敏感操作日志输出,关注异常 |
生产环境部署前应通过 dab validate 校验配置文件的语法和引用完整性:
dab validate --config ./dab-config.json安全机制跨协议一致性
REST、GraphQL 和 MCP 共享同一套安全配置。无论在哪种协议中发起请求:
- 身份验证流程一致,角色判定逻辑相同。
- 实体权限、字段过滤、行级策略在所有协议中同样生效。
- MCP 工具列表只包含当前角色有权限的实体和操作。
这意味着你不需要为不同协议单独配置安全规则。配置一次,三种协议同时受保护。
MCP 特殊说明
- Stdio 模式身份验证:Stdio 模式下自动使用 Simulator 身份验证,覆盖配置文件中的身份验证设置。角色通过
role:<role-name>参数指定,仅用于本地开发。 - 请求大小限制:Stdio 模式下传入请求大小限制为 1 MB,防止恶意大请求消耗资源。
- 自定义工具权限:存储过程实体的
custom-tool同样受实体权限控制,只有配置了execute权限的角色才能调用对应的自定义 MCP 工具。 - 工具可见性:在运行时层面禁用某个 DML 工具(如
delete-record)后,该工具对所有角色不可见,即使实体权限允许删除操作。
监控与审计
生产环境中应持续监控安全事件:
- 日志:记录身份验证失败、权限拒绝和异常请求,级别建议
Warning。 - 追踪:通过 OpenTelemetry 追踪请求的完整链路,包括认证和授权决策。
- 健康检查:
/health端点可配置角色限制,确保只有授权方才能探测服务状态。 - 审计:定期审查
permissions配置变更记录(Git 历史),确保权限变更可追溯。
健康检查端点安全配置
生产环境中应限制健康检查端点的访问:
{
"runtime": {
"health": {
"allowedRoles": ["monitoring"]
}
}
}这样只有携带 monitoring 角色的请求才能访问 /health 端点,防止未授权方探测服务状态。
安全配置速查
| 需求 | 配置位置 | 相关文档 |
|---|---|---|
| 启用 JWT 身份验证 | runtime.host.authentication | 身份验证概述 |
| 配置自定义 JWT(Okta/Auth0) | runtime.host.authentication.jwt | 自定义 JWT 身份验证 |
| 授予匿名用户只读权限 | entities.{name}.permissions | 授权概述 |
| 对角色隐藏敏感字段 | permissions.actions.fields | 授权概述 |
| 按用户过滤数据行(数据库策略) | permissions.actions.policy | 数据库策略 |
| 按用户过滤数据行(SQL Server RLS) | data-source.options.set-session-context | 行级安全 |
| 保护配置文件密钥 | @env('VAR_NAME') | 环境变量与密钥 |
| 关闭生产环境调试信息 | host.mode: production | 服务运行配置 |
| 查看最终解析权限 | CLI 命令 | dab configure --show-effective-permissions |
