使用 CASL 和 graphql-shield 的 GraphQL 后端 RBAC 以及与我的 React 前端共享规则

如何解决使用 CASL 和 graphql-shield 的 GraphQL 后端 RBAC 以及与我的 React 前端共享规则

我正在运行 Mongoose 并使用 GraphQL (Apollo) 公开 API。

我想实现一个 RBAC,经过一些研究,我提出了一个使用 CASL 和 graphql-shield 的解决方案。 理想情况下,我希望与我的 React 前端共享规则。


第一步,在一张纸上计划。

我将首先定义我的操作:创建、读取、更新、删除。

然后我会定义我的主题:汽车、摩托车。

完成后,我将继续定义我的角色:CarSpecialist、MotoSpecialist、Admin。 然后我会定义一些条件:“主题是我自己的”等。

最后,我会为每个角色分配一组能力(动作、主题、条件的组合)。


现在完成所有这些工作后,我开始实际编写我的解决方案。

我首先在 CASL 中编写能力:动作和主题非常容易定义。

条件有点棘手,我至少有两个选择:

  • 我使用“模糊”的概念,而这些概念又必须由任何需要强制执行它们的人(后端或前端)来解释。

  • 我使用 CASL mongoose 集成插件,但代价是无法与我的前端共享。


有什么可以选择的输入吗?

现在一旦定义了 CASL 能力,是否由 graphql-shield 来执行它们?

如何将 (CASL) 操作、主题和条件映射到 graphql 术语:架构、查询、突变......?

解决方法

我会尽量回答这个问题:

  1. 如果使用默认条件,您不会失去与 UI 共享权限的能力。当您运行 ability.can 时,条件在 js 中被解释。因此,如果 mongo 查询语言适合您,那么无需更改它!
  2. Graphql shield 是一种特殊的 graphql 中间件。如果您使用 casl 和 graphql 中间件,您不需要 graphql shield! 使用 casl + 自定义 graphql 中间件或 graphql-shield
  3. 每个 graphql 类型都有底层源类型。源类型基本上是您的域模型或只是封装业务逻辑的数据库模型。这是您的映射 :) 只需检查源类型的权限即可。但是,如果您与 UI 共享权限,那么您需要将为源类型编写的后端权限(在发送到 UI 之前)转换为可以应用于 graphql 类型的权限!或者,您可以将一些私有属性(例如 Car 的 ownerId)公开为 graphql 类型的一部分。但如果这样做的唯一目的是满足权限共享,那么我会选择转换选项:
function defineAbility(user,props) {
   const { can,rules} = new AbilityBuilder(Ability)

   can('read','Post',{ [props.authorId]: user.id })
   // ...

   return rules;
}

const currentUser = { id: 1 }
const backendRules = defineAbility(currentUser,{
  authorId: 'authorId'
});

const uiRules = defineAbility(currentUser,{
  authorId: 'author.id'
});

或者,您可以通过在每个 graphql 类型上公开子类型来检查后端的权限并与前端共享结果:


{
   cars {
     items {
       permissions {
         canUpdate
         canRead
       }
     }
   }
}

这样做的后果是您的服务器将花费更多时间来生成响应,尤其是在您检索用于分页的项目时。因此,在继续之前检查响应时间。这样做的好处是你不需要在 UI 上使用 casl,并且权限检查逻辑完全隐藏在后端

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-