基于site_uuid的Hasura多租户数据访问限制方案咨询
在Hasura中基于site_uuid实现多租户数据访问控制(含_by_pk查询)
我完全懂你的需求——通过请求头传递site_uuid,让Hasura自动给所有查询(包括单个对象的_by_pk查询)加上site_uuid校验,实现多租户共享数据库的隔离。下面是亲测有效的具体实现步骤:
1. 把请求头的site_uuid映射为Hasura会话变量
首先得让Hasura识别并转发请求头里的site_uuid作为会话变量:
- 登录Hasura控制台,进入Settings > Environment Variables,确保已设置
HASURA_GRAPHQL_UNAUTHORIZED_ROLE(比如设为tenant_user),同时保持HASURA_GRAPHQL_ENABLE_CONSOLE为true方便操作。 - 你可以直接在请求头里用
x-hasura-site-uuid作为键,Hasura会自动把它转换成同名的会话变量,只要后续给角色配置权限时允许访问这个变量即可。
2. 给所有表配置全局行级权限
这是实现租户隔离的核心,针对每个包含site_uuid字段的表:
- 进入Data > [目标表] > Permissions,选择你要配置的角色(比如
tenant_user),找到Select权限(这个权限覆盖了_by_pk、列表查询、聚合查询等所有读取操作)。 - 在Row select permission的条件输入框里,填写:
{"site_uuid": {"_eq": "{{$session_variables['x-hasura-site-uuid']}}"}} - 保存配置,对所有表重复这个操作。
为什么_by_pk查询会生效?
Hasura的行级权限是全局叠加的,不管你用哪种查询方式(_by_pk、find_first还是列表查询),都会自动把这个site_uuid校验条件加到SQL里。比如你调用users_by_pk(id: "123")时,Hasura实际执行的SQL会是:
SELECT * FROM users WHERE id = '123' AND site_uuid = '请求头传入的site_uuid';
如果该记录的site_uuid不匹配,会返回null,完美实现租户数据隔离。
3. 测试验证
用Hasura控制台的GraphiQL或者其他GraphQL客户端发送请求:
- 在请求头里添加:
x-hasura-site-uuid: your-test-site-id - 调用
_by_pk查询:query { users_by_pk(id: "123") { id name site_uuid } } - 验证结果:如果该用户的
site_uuid和请求头一致,会返回数据;否则返回null,说明权限生效。
额外优化(可选)
如果需要自动给插入的记录填充site_uuid,可以在Insert权限里设置Column presets,把site_uuid设为{{$session_variables['x-hasura-site-uuid']}},这样租户插入数据时不需要手动传site_uuid,Hasura会自动填充,避免人为错误。
内容的提问来源于stack exchange,提问作者Jaybeecave
相关产品推荐
相关产品推荐

