Skip to content

12 — 平台表 GraphQL 查询(HMAC)

第三方通过 HMAC 调用门户,对管理端已纳入 catalog 且审核授予的平台物理表执行只读 GraphQL 单表查询

须先申请、后调用:未经审核通过的 Client grant,GraphQL Schema 中看不到对应表。
设计方案doc/51-通用单表GraphQL查询.md
与 JDBC 视图区别09-数据服务-JDBC视图-HMAC.md 查第三方库映射 JSON;本文查平台库白名单表。

查询基路径/api/open/tables
查询方法POST /graphql


1. 接入流程

text
1. 打开公开申请页 https://{portal}/open/data-query-apply
2. POST /api/portal/data-query/applications(选表、填用途与联系方式)
3. 等待管理端审核 → APPROVED(绑定 CONFIDENTIAL Client,写入 grant)
4. 使用 bound_client_id + client_secret 调 POST /api/open/tables/graphql
阶段路径鉴权
可选表清单GET /api/portal/data-query/catalog/open无(仅 apply_open=1
提交申请POST /api/portal/data-query/applications
进度查询GET /api/portal/data-query/applications?applyCode=无(持 applyCode
GraphQL 查询POST /api/open/tables/graphqlHMAC

公开申请页路由:/open/data-query-apply(前端独立页,非 /api)。


2. 申请 API(门户公开)

2.1 可选表 — GET /api/portal/data-query/catalog/open

响应 data 为数组:tableNametableLabel(仅 catalog apply_open=1enabled=1)。

2.2 提交 — POST /api/portal/data-query/applications

字段必填说明
orgName单位名称
contactName联系人
contactPhone电话
contactEmail邮箱
purpose用途说明
requestClientId期望复用的 client_id(须已存在且 CONFIDENTIAL)
tableNames字符串数组;须在 open catalog 内

成功 dataapplyCodestatus=PENDING

2.3 进度 — GET /api/portal/data-query/applications?applyCode=

字段说明
applyCode申请单号
statusPENDING / APPROVED / REJECTED / REVOKED
reviewComment审核意见(驳回/通过)
boundClientId通过后绑定的 Client(方可调 GraphQL)
tableNames申请明细

3. GraphQL 查询 — POST /api/open/tables/graphql

3.1 鉴权头

02-事项推送-HMAC.md09-数据服务-JDBC视图-HMAC.md 完全一致

Header必填说明
X-Client-Id审核通过绑定的 client_id
X-TimestampUnix
X-SignatureHMAC-SHA256 Hex

签名串:

text
{clientId}\n{timestamp}\n{rawBody}

时间窗:±300 秒

Client 要求

  • client_type=CONFIDENTIAL 且启用
  • 已绑定 system_code
  • 审核通过后存在 sys_data_query_grantprincipal_type=HMAC_CLIENTprincipal_code={clientId}enabled=1

未开通 grant_type=client_credentials

3.2 请求 Body

字段必填说明
queryGraphQL 查询字符串
variables变量 JSON
operationName多操作时指定

3.3 响应(ApiResult 例外)

本接口 使用门户统一 ApiResult 包装,直接返回 GraphQL 规范 JSON:

json
{
  "data": {
    "sysUser": {
      "total": 100,
      "pageNum": 1,
      "pageSize": 20,
      "records": [
        { "username": "zhangsan", "realName": "张三", "deptCode": "D001", "deptName": "研发部" }
      ]
    }
  },
  "errors": null
}
场景HTTPbody
成功200{ "data": {...}, "errors": null }
部分字段失败200data + errors[](含 pathmessage
鉴权失败200 或 401errors[].extensions.code=UNAUTHENTICATED
无 grant / 表不可见200errors 提示未知字段或 FORBIDDEN
签名错误200code 非 0 的 ApiResult(Filter 层拒绝,未进 GraphQL)

注意:仅 GraphQL 执行成功进入引擎 的响应为 {data,errors};HMAC Filter 拒绝(Client 无效、签名错、非 CONFIDENTIAL)仍为 ApiResult 包装,与 02/09 一致。

3.4 示例

bash
BODY='{"query":"query { sysUser(pageNum:1, pageSize:10) { total records { username realName } } }"}'
TS=$(date +%s)
SIG=$(printf '%s\n%s\n%s' "$CLIENT_ID" "$TS" "$BODY" | openssl dgst -sha256 -hmac "$CLIENT_SECRET" | awk '{print $2}')

curl -sS -X POST "https://portal.example.com/api/open/tables/graphql" \
  -H "Content-Type: application/json" \
  -H "X-Client-Id: $CLIENT_ID" \
  -H "X-Timestamp: $TS" \
  -H "X-Signature: $SIG" \
  -d "$BODY"

4. Schema 与授权

  • GraphQL Schema 动态生成:仅包含该 Client 有 grant 且 catalog enabled=1 的表。
  • 未授权表:不出现在 Schema(查询未知字段报错,而非返回空列表)。
  • 列:受 doc/42 字段元数据约束(开放面使用 Client 绑定 system_code 下配置的默认字段权限或专用开放角色)。
  • 行:受 doc/45/doc/46 与 catalog 锚点列约束。

5. 错误码摘要

场景典型
Client 非 CONFIDENTIALFilter:code=403,message 说明 Client 类型
无 grantGraphQL FORBIDDEN
表未在 catalog未知字段
分页超限pageSize > 200 → BAD_USER_INPUT
申请未通过调 GraphQL无 grant,Schema 无表

6. 与 MCP 的边界

能力路径鉴权
Agent 按登录用户查平台表POST /api/open/mcp/graphql工具令牌 + mcp:data:query11-MCP.md
第三方系统级批查POST /api/open/tables/graphql本文 HMAC
第三方库视图 JSONPOST /api/open/data/queryHMAC(09

7. 非目标

  • 申请前调用 GraphQL
  • PUBLIC Client、client_credentials
  • Mutation / 任意 SQL
  • 未审核表「先试再申请」