Prisma 认证与授权迁移指南:从 Graphcool Framework 迁移 Authentication 到应用层
后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载本指南讲解如何将原有 Graphcool Framework 服务中的认证Authentication与授权Authorization功能迁移到 Prisma 架构Prisma 不再把用户认证与权限系统绑定而是提供基于 JWTService Token的简单令牌机制用户注册/登录与数据访问权限如只有作者才能更新自己的 Post全部下沉到 GraphQL 服务器的应用层实现。读完本文你将掌握签名与校验 Prisma 服务令牌、用prisma-binding的exists函数替代 Graphcool 权限查询permission queries以及用graphql-yogabcryptjsjsonwebtoken完整落地 signup / login / 权限校验的实战方案。背景Graphcool Framework 的认证与授权方式在 Graphcool Framework 中认证功能通过 resolver functions解析器函数实现对 API 的 GraphQL schema 做扩展追加提供注册signup和登录login能力的专用 mutation。整个过程通常包含三个步骤在 GraphQL schema 的Mutation类型上以 schema extension 的形式定义signup/loginresolver 函数直接在 Graphcool Framework 中以 JavaScript 提供这些 resolver 函数的实现或使用 webhook 调用你自行托管的函数在 service 定义文件中把 mutation 定义与实现连接起来。而在数据访问的安全控制方面Graphcool Framework 使用permission queries权限查询概念每个 API 操作都可以关联一条或多条权限规则在执行操作前先进行校验。这种把认证与权限都耦合进框架的方式带来的架构问题是认证逻辑、业务逻辑与数据层界限模糊。Prisma 对此做了彻底调整。Prisma 的认证概念为什么功能被移入应用层Prisma 的 authentication 概念与 Graphcool Framework 截然不同Prisma 不提供用户级认证。它只提供一个简单的、基于令牌可以理解为API Key的系统用于访问 Prisma API——即 service secret 与 service token 机制用户认证与权限规则移入应用层即你的 GraphQL 服务器graphql-yoga等负责实现prisma-binding包提供的exists函数在应用层扮演与 Graphcool Framework 中权限查询类似的角色JWT 令牌改由你自己生成而不再由graphcool-lib代为生成。这一设计对应迁移指南 Overview 中描述的两层架构Prisma 提供数据库层自动生成、面向 CRUD 的 GraphQL API你的 GraphQL 服务器构成应用层面向客户端、承载业务逻辑、认证与权限。prisma-binding负责把应用层的请求转发给 Prisma API。理解 Prisma 的服务密钥与令牌机制在动手迁移之前先理解 Prisma 自身的认证基础。Prisma 服务的 GraphQL API 默认由 service secret 保护它定义在prisma.yml中service: my-service stage: ${env:PRISMA_STAGE} cluster: ${env:PRISMA_CLUSTER} datamodel: database/datamodel.graphql secret: ${env:PRISMA_SECRET}secret的约束必须是 UTF-8 编码、不能包含空格、最长 256 字符也可以在单个字符串中以逗号分隔多个 secret空格会被忽略从而实现无缝密钥轮换secret: myFirstSecret, SECRET_NUMBER_2,3rd-secret如果设置disableAuth: true则任何人都拥有数据库的完整读写权限默认是false即默认启用认证。secret用于签发 JWT 服务令牌令牌放在 HTTP 请求的Authorization头中Authorization: Bearer __TOKEN__JWT 载荷payload包含两类必须的 claims{ exp: 1300819380, service: my-serviceprod }exp令牌过期时间service服务的名称与 stage。Prisma 校验请求时会检查令牌必须用服务配置的 secret 签名、exp必须指向未来、serviceclaim 必须与当前请求的服务及 stage 匹配。prisma.yml的完整字段定义可参考 YAML-Structure。在 Node 端可以基于jsonwebtoken库自行签发这样的服务令牌这里的PRISMA_SECRET/PRISMA_STAGE来自环境变量var jwt require(jsonwebtoken) jwt.sign( { data: { service: my-service process.env.PRISMA_STAGE, }, }, process.env.PRISMA_SECRET, { expiresIn: 1h, } )也可以直接用 CLI 命令prisma token获取当前 Prisma 服务的新签名 JWT支持--copy复制到剪贴板与--env-file指定环境变量文件详见 prisma-tokenprisma token prisma token --copy在源码层面prisma-client-lib的 Client 构造函数会在传入secret时自动用它签发空载荷令牌sign({}, secret)并把它作为Authorization: Bearer token头附加到对 Prisma API 的所有请求包括订阅的connectionParams。也就是说应用层服务器与 Prisma 之间的服务级认证是自动完成的你在应用层要操心的是你的用户与你的 GraphQL 服务器之间的用户认证。迁移前提以下迁移步骤假设你使用graphql-yoga作为 GraphQL 服务器你的 schema 定义使用 SDLSchema Definition Language编写。想直接看现成实现可参考本仓库examples/目录下的示例仓库中examples目录目前只包含说明文件完整的 auth / permissions 示例在 Prisma 官方示例仓库中。另有配套教程 Permissions 详述权限规则的实现。迁移 Step 1迁移 Schema 定义假设你的 Graphcool Framework 服务中曾定义过如下 schema extensiontype Mutation { signupUser(email: String!, password: String!): SignupUserPayload authenticateUser(email: String!, password: String!): AuthenticateUserPayload } type SignupUserPayload{ userId: ID! token: String! } type AuthenticateUserPayload { token: String! }其中signupUser与authenticateUsermutation 用于注册和登录。返回的token是由graphcool-lib生成的 JSON Web Token客户端把它放进AuthorizationHTTP 头即可对 API 发起认证请求。迁移时把这些定义挪进你的graphql-yoga服务器的 schema 定义即可。这里还有个额外的好处Graphcool 时期由于 resolver 函数无法返回模型类型model types而被迫做的 workaround 也可以一并去掉。例如新定义可以简化为type Mutation { signup(email: String!, password: String!): AuthPayload login(email: String!, password: String!): AuthPayload } type AuthPayload { token: String! user: User! }AuthPayload直接返回User对象schema 更干净也更能表达业务语义。迁移 Step 2迁移 Resolver 函数接下来为上面定义的signup和loginmutation 实现 resolver。核心变化是JWT 由你自己用jsonwebtoken生成密码哈希用bcryptjssignupresolver 中还负责创建新的User节点。auth.jsconst bcrypt require(bcryptjs) const jwt require(jsonwebtoken) const auth { async signup(parent, args, ctx, info) { const password await bcrypt.hash(args.password, 10) const user await ctx.db.mutation.createUser({ data: { ...args, password }, }) return { token: jwt.sign({ userId: user.id }, process.env.JWT_SECRET), user, } }, async login(parent, { email, password }, ctx, info) { const user await ctx.db.query.user({ where: { email } }) if (!user) { throw new Error(No such user found for email: ${email}) } const valid await bcrypt.compare(password, user.password) if (!valid) { throw new Error(Invalid password) } return { token: jwt.sign({ userId: user.id }, process.env.JWT_SECRET), user, } }, } module.exports { auth }几点说明signup中ctx.db.mutation.createUser是经由prisma-binding生成的 Prisma mutationdata: { ...args, password }中args包含email与password其中密码已替换为 bcrypt 哈希后的值——绝不能把明文密码写进数据库login用ctx.db.query.user({ where: { email } })按唯一字段email查询用户然后bcrypt.compare校验密码两个 resolver 都用jwt.sign({ userId: user.id }, process.env.JWT_SECRET)生成用户令牌这里的JWT_SECRET是应用层的密钥与 Prisma 的 service secret 不是一回事——它只用于签名你是谁的用户令牌。AuthPayload.js解析user字段避免把整棵User对象直接暴露const AuthPayload { user: async ({ user: { id } }, args, ctx, info) { return ctx.db.query.user({ where: { id } }, info) }, } module.exports { AuthPayload }把token与user解耦后可以确保只查询客户端真正请求的User字段info会被透传给 Prisma。如何识别当前请求用户在上面login之后所有受保护的 resolver 都要先从请求上下文恢复userId。常见做法是封装一个getUserId(ctx)工具从ctx.request的Authorization头中取出Bearer token用jsonwebtoken.verify验签得到userId验签失败则抛出未认证错误。这也是下方权限校验代码中getUserId(ctx)的语义基础——它在用户未认证时直接抛错。迁移 Step 3迁移权限规则如前所述prisma-binding的exists函数是迁移权限查询的首选工具。它生成的ctx.db.exists.Type(filter)会在数据库中检查是否存在满足条件的节点返回布尔值非常适合在 resolver 内做前置条件判断。在源码层面prisma-client-lib的 Client 类对外暴露$exists即ctx.db.exists的底层实现并在构造时通过this.buildExists()构建按模型类型生成exists.Post(...)/exists.User(...)这样的方法。场景只允许作者更新自己的 Post假设你的 Prisma 服务数据模型如下type User model { id: ID! unique name: String! posts: [Post!]! } type Post model { id: ID! unique title: String! author: User! }在 Graphcool Framework 中要表达只有Post的作者能更新它你需要给updatePostmutation 关联如下 permission queryquery ($user_id: ID!, $post_id: ID!) { SomePostExists(filter: { id: $post_id author: { id: $user_id } }) }而在 Prisma 中你需要在应用层的updatePostresolver 里完成同样的检查async function updatePost(parent, { id, title, text }, ctx, info) { // getUserId throws an error if the requesting user is not authenticated const userId getUserId(ctx) // this expresses the same condition as the permission query above const requestingUserIsAuthor await ctx.db.exists.Post({ id, author: { id: userId, }, }) // only if the condition is true, the post is actually updated if (requestingUserIsAuthor) { return await ctx.db.mutation.updatePost({ where: { id }, data: { title, text }, }, info) } throw new Error( Invalid permissions, you must be an admin or the author of a post to update it, ) }注意对应关系Graphcool FrameworkPrisma 应用层permission query如SomePostExistsctx.db.exists.Post({ ... })框架内自动执行权限检查resolver 内显式检查通过后才执行ctx.db.mutation.*$user_id由框架注入getUserId(ctx)从请求令牌解析检查失败由框架返回错误检查失败抛Error由 GraphQL 服务器统一返回扩展组合多个权限条件作者或管理员exists不仅支持单条条件还支持组合判断。比如作者本人或ADMIN用户才能读取某篇 Postasync post(parent, { id }, ctx, info) { const userId getUserId(ctx) const requestingUserIsAuthor await ctx.db.exists.Post({ id, author: { id: userId, }, }) const requestingUserIsAdmin await ctx.db.exists.User({ id: userId, role: ADMIN, }) if (requestingUserIsAdmin || requestingUserIsAuthor) { return ctx.db.query.post({ where: { id } }, info) } throw new Error( Invalid permissions, you must be an admin or the author of this post to retrieve it., ) }这里的关键是给User增加role字段配合Role枚举ADMIN/CUSTOMER默认CUSTOMER且role与password一样不要暴露在应用层 schema中从而对客户端隐藏。更完整的可运行示例drafts、publish、deletePost等 resolver 的逐步改造参见 Permissions 教程。在 GraphQL Playground 中验证认证与权限完成迁移后可以用 GraphQL Playground 验证流程启动服务器yarn start打开http://localhost:4000发送signupmutation 创建用户并返回tokenmutation { signup( email: sarahgraph.cool password: graphql name: Sarah ) { token } }复制返回的token在 Playground 左下角的 HTTP Headers 中以 JSON 形式设置为Authorization头把__TOKEN__替换为真实令牌{ Authorization: __TOKEN__ }之后所有请求都代表该用户发出可以验证用另一个用户登录后尝试发布 Sarah 的 draft会得到Post not found or youre not the author之类的错误。小结从框架到 Prisma 的认证/授权心智模型迁移完成后你的架构变成了清晰的双 GraphQL 层Prisma数据库层只认 service tokenJWT由 service secret 签发提供纯粹的 CRUD 数据访问能力不做任何用户级权限判断你的 GraphQL 服务器应用层负责用户注册/登录、生成用户 JWT、解析当前请求用户getUserId、用ctx.db.exists实现细粒度权限校验再把合法请求转发给 Prisma。这套模式的收益是认证与授权逻辑完全由你掌控schema 更简洁AuthPayload直接返回user权限规则用普通 JavaScript 表达、可组合可测试同时 Prisma 侧的 API 可以保持通用、复用和可预测。赞分享后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载相关推荐Prisma 迁移指南从 Graphcool Framework 到 Prisma 的认证与授权Authentication AuthorizationPrisma 迁移指南从 Graphcool Framework 到 Prisma 的认证与授权Authentication Authorization后端数据库GraphQL从 Graphcool Framework 到 Prisma认证与授权Authentication Authorization迁移完整指南从 Graphcool Framework 到 Prisma认证与授权Authentication Authorization迁移完整指南 本篇指南以后端数据库GraphQLPrisma 认证与授权迁移指南从 Graphcool Framework 到应用层 JWT 实现Prisma 认证与授权迁移指南从 Graphcool Framework 到应用层 JWT 实现 本文基于 Prisma 官方迁移指南对应仓库文档 doc后端数据库GraphQL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

U盘扩容盘修复指南:用APTool v7200将128G打回真实32G

U盘扩容盘修复指南:用APTool v7200将128G打回真实32G

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 11:34:44 阅读更多 →
Trae与Cursor深度对比:免费积分与订阅生态,谁更适合你的AI编程工作流?

Trae与Cursor深度对比:免费积分与订阅生态,谁更适合你的AI编程工作流?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 11:34:43 阅读更多 →
RISC-V vs ARM:嵌入式选型实战指南与迁移避坑

RISC-V vs ARM:嵌入式选型实战指南与迁移避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 11:34:43 阅读更多 →

最新新闻

HG680-MC救砖全指南:TTL刷机与当贝桌面净化

HG680-MC救砖全指南:TTL刷机与当贝桌面净化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:29:20 阅读更多 →
【单片机毕设案例分享】基于 STM32 的按键参数配置与物联网智能水族系统设计 基于 STM32 的水位阈值检测与自动补水控制系统设计(011409)

【单片机毕设案例分享】基于 STM32 的按键参数配置与物联网智能水族系统设计 基于 STM32 的水位阈值检测与自动补水控制系统设计(011409)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于单片机,STM32单片机,51单片机,J…

2026/9/24 12:29:20 阅读更多 →
24款AI Agent横向评测:六维雷达图与选型避坑指南

24款AI Agent横向评测:六维雷达图与选型避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:29:20 阅读更多 →
【单片机课设毕设项目】基于 STM32 的 WiFi 无线传输养殖状态监测系统设计 基于 STM32 的手动 / 定时双模式智能投喂装置设计与实现(011409)

【单片机课设毕设项目】基于 STM32 的 WiFi 无线传输养殖状态监测系统设计 基于 STM32 的手动 / 定时双模式智能投喂装置设计与实现(011409)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/9/24 12:29:20 阅读更多 →
如何实现淘宝自动提报活动自动化?秒级轮询竞品监控,别人调价你3秒内自动跟进

如何实现淘宝自动提报活动自动化?秒级轮询竞品监控,别人调价你3秒内自动跟进

如何实现淘宝自动提报活动自动化?秒级轮询竞品监控,别人调价你3秒内自动跟进 做电商这么多年,最大的感悟就是:淘宝的自动提报活动,是店群运营中最耗人力也最容易出错的环节。 平台大促活动报名是流量红利窗口&#xff…

2026/9/24 12:29:20 阅读更多 →
FT232R驱动安装全攻略:Windows/Linux/macOS配置与问题排查

FT232R驱动安装全攻略:Windows/Linux/macOS配置与问题排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 12:28:19 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →