ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PostGraphile v5 默认角色(Default Role)详解:authenticator 角色、角色切换与权限边界设计

PostGraphile v5 默认角色(Default Role)详解:authenticator 角色、角色切换与权限边界设计 后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载本篇指南围绕 PostGraphile v5 文档中的“默认角色”概念展开讲解 PostgreSQL 角色体系的层级与登录权限、PostGraphile 中authenticator角色的职责与安全边界noinherit以及如何通过preset.grafast.context中的pgSettings.role在请求级别动态切换角色。读完本文你将掌握从建库授权、连接认证到请求级角色注入的完整链路并能在自己的 PostGraphile 项目中落地一套“最小权限 按需提权”的数据库访问方案。PostGraphile 充分使用了 PostgreSQL 的角色role机制数据库端的所有权限控制都建立在角色之上服务端则通过连接串指定的角色进入数据库再在每次请求中按需切换到目标角色。理解这一模型是正确配置 PostGraphile 权限体系的前提。PostgreSQL 角色基础角色、用户与权限PostgreSQL 通过CREATE ROLE创建任意数量的角色并通过GRANT将权限授予角色。权限形如“从post表执行 SELECT”“向person表插入行”等细粒度操作例如grant select on post to reader; grant insert on person to editor;角色具有层级角色可以“授予”给角色PostgreSQL 角色是分层的——你可以把角色授予其他角色。例如有角色editor可修改数据库中的数据和角色admin执行grant editor to admin;之后admin就拥有了editor的全部权限。同时admin还能在会话中把自己切换SET ROLE为editor——这意味着切换后本次会话中你将不再拥有admin的权限而只拥有editor角色被授予的权限。这种“降权”能力正是 PostGraphile 权限模型的核心机制。用户就是可登录的角色在 PostgreSQL 中“用户”user本质上就是可以登录LOGIN的角色。以下两条语句完全等价都创建了一个可以登录的admin角色即用户create role admin login; create user admin;而下面两条语句同样等价创建了一个不能登录的角色create role editor; create user editor nologin;所谓“登录”指的是该角色可以用于连接串的认证部分。以上面的角色为例你可以使用postgres://adminlocalhost/mydb建立连接但postgres://editorlocalhost/mydb会被拒绝。PostGraphile 中的角色authenticator 与角色切换连接串中的 authenticatorPostGraphile 要求你在连接服务器时至少提供一个可登录的用户角色。这个角色写在连接串中此后统称为authenticator认证者。典型启动方式postgraphile -c postgres://authenticatorlocalhost/mydbauthenticator拥有 PostGraphile 运行时可能需要的一切权限——其中最重要、也往往唯一需要的权限就是切换到某些特定角色的能力。同时它应当被严格限制只能“看到”被允许暴露的数据。noinherit更强的安全边界authenticator可以通过授权获得切换到其他角色的能力例如grant visitor to authenticator;如果在创建authenticator时加上noinherit选项create role authenticator login noinherit ...;那么authenticator自身不继承被授予角色的权限必须显式执行set role to visitor;之类切换后才能真正拿到目标角色的权限。这构成了一道很好的安全边界连接进程在默认状态下没有任何业务权限只有显式切换后才拥有对应角色的能力。从源码看PostGraphile 的测试套件正是按这一模式组织的在 kitchen-sink-permissions.sql 中postgraphile_test_authenticator只被授予usage于各 schema以及少数必要的枚举表查询权限而postgraphile_test_visitor才拥有对c.person、a.post等业务表的select/insert/update/delete且多为列级授权。两者一“薄”一“厚”正体现了“authenticator 仅负责切换业务权限全部集中在业务角色”的设计意图。在请求中触发角色切换pgSettings.rolePostGraphile 中角色切换通过role设置项触发该项可以在preset.grafast.context回调中填充详见 config/context.mdx。一个完整的graphile.config.mjs示例import { PostGraphileAmberPreset } from postgraphile/presets/amber; export default { extends: [PostGraphileAmberPreset], grafast: { context(requestContext, args) { // Extract the session user from the request context, e.g. const user requestContext.expressv4?.req?.user; // Start with the role weve already set it to - e.g. via the JWT plugin let role args.contextValue.pgSettings?.role; // If this is unset: default to visitor if logged in, anonymous otherwise role ?? user ? visitor : anonymous; return { pgSettings: { // Override the role in the pgSettings ...args.contextValue.pgSettings, role, }, }; }, }, };这段配置的逻辑非常直观先从请求上下文如 Express 中间件注入的req.user判断当前会话用户读取已有的pgSettings.role例如 JWT 插件已经写入的值作为起点若未设置则根据是否登录回退为visitor已登录或anonymous匿名返回新的pgSettings其中的role覆盖旧值。这样每个 GraphQL 请求都会携带一个明确的数据库角色PostGraphile 在执行查询前切换到该角色从而实现“同一套服务、按登录态访问不同数据”的效果。从源码看 pgSettings 的底层执行链路pgSettings不止承载role它是Recordstring, string | undefined | null形式的通用设置集合见 executor.ts。除了role之外你还可以放入search_path、timezone等任意 Postgres GUC 设置。在数据库执行层面dataplan-pg 的适配器会把pgSettings中的键值对序列化后通过set_config在事务内生效源码 pg.ts 显示只要存在非空的设置项就会先执行begin或savepoint随后执行select set_config(el-0, el-1, true) from json_array_elements($1::json) el其中$1是JSON.stringify(pgSettingsEntries)得到的键值对数组。注意set_config的第三个参数为true表示设置仅在当前事务内有效——请求结束后随事务提交/回滚自动恢复不会污染连接池中其他请求的状态。若执行出错则会回滚并重新抛出异常见 pg.ts。与其他角色注入方式的配合旧的 pgSettings 选项已被标记为废弃在 PostGraphile v4 中开发者通过pgSettings选项DirectOrCallbackRequest, Recordstring, string注入角色等设置。在 v5 中该选项仍保留兼容但已被明确标记为deprecated注释直接指向新的做法“Please use grafast.context pgSettings key instead”见 presets/v4.ts。新项目应直接使用preset.grafast.context回调返回pgSettings。JWT 插件如何写入 role仓库中的PgLazyJWTPreset见 presets/lazy-jwt.ts展示了另一条角色注入路径当请求头携带Authorization: Bearer token时插件校验 JWT 后若 claims 中存在role字段会写入pgSettings.role其余 claims 则以jwt.claims.key的形式写入pgSettings键名需匹配^[a-z_][a-z0-9_]*$且长度不超过 52。这也是示例代码中“Start with the role weve already set it to - e.g. via the JWT plugin”所引用的事实来源。插件作者在注释中特别提醒你应当自己在preset.grafast.context中处理 JWT以便完全掌控校验规则只把真正需要的值传给 Postgres见 presets/lazy-jwt.ts——这与本文示例中“先读取 JWT 写入的 role、再按需覆盖”的做法一脉相承。最佳实践小结最小权限的 authenticator连接串中的角色只授予必要的usage与切换权限并配合noinherit使用使其默认不持有任何业务权限业务角色分离为“访客”“匿名”“管理员”等语义分别建立nologin角色集中授予各自所需的数据权限请求级角色注入在preset.grafast.context中根据会话身份决定pgSettings.role让每个请求以最小必要权限执行数据库操作避免连接串复用特权角色不要在连接串中直接使用拥有全部权限的角色否则任何请求都可能以最高权限访问数据库。借助 PostgreSQL 原生的角色层级与SET ROLE机制PostGraphile 得以在应用层实现精细、可审计的数据库访问控制——理解默认角色模型是安全使用 PostGraphile 的第一步。本文基于仓库中 default-role.md 文档整理并结合 dataplan-pg 与 postgraphile 源码验证其实现细节。赞分享后端API网关【免费下载链接】crystal Graphiles Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!项目地址https://gitcode.com/gh_mirrors/cry/crystal点击查看免费下载相关推荐Default Role默认角色PostGraphile 的 PostgreSQL 角色安全模型入门Default Role默认角色PostGraphile 的 PostgreSQL 角色安全模型入门 output文章 PostGraphile 默认角后端API网关深入解析 PostGraphile 默认角色机制authenticator 与 role 切换的完整实战指南深入解析 PostGraphile 默认角色机制authenticator 与 role 切换的完整实战指南 导读 PostGraphile 将 Postgr后端API网关NocoBase 角色并集Role Union多角色权限合并机制详解NocoBase 角色并集Role Union多角色权限合并机制详解 在 NocoBase 中一个用户可以被赋予多个角色而“角色并集”Role Uni低代码后端前端人工智能AI 应用工作流自动化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表