权限框架之jcasbin讲解

news2024/11/24 7:54:22

文章目录

  • 1 jcasbin
    • 1.1 前言
    • 1.2 工作原理
      • 1.2.1 PERM模型
      • 1.2.2 Model语法
        • 1.2.2.1 Request定义
        • 1.2.2.2 Policy定义
        • 1.2.2.3 Policy effect定义
        • 1.2.2.4 角色定义
        • 1.2.2.5 匹配器
        • 1.2.2.6 完整model.conf
      • 1.2.3 policy.csv
    • 1.3 准备
      • 1.3.1 mavan依赖
      • 1.3.2 配置文件
      • 1.2.3 读取权限信息进行初始化
    • 1.4 使用
      • 1.4.1 权限控制
      • 1.4.2 添加删除权限

1 jcasbin

1.1 前言

作为一名后台开发人员,权限这个名词应该算是特别熟悉的了。就算是java里的类也有 publicprivate权限之分。之前项目里一直使用shiro作为权限管理的框架。说实话,shiro的确挺强大的,但是它也有很多不好的地方。shiro默认的登录地址还是login.jsp,前后端分离模式使用shiro还要重写好多类;手机端存储用户信息、保持登录状态等等,对shiro来说也是一个难题。
在分布式项目里,比如电商项目,其实不太需要明确的权限划分,说白了,认为没必要做太麻烦的权限管理,一切从简。何况shiro对于springCloud等各种分布式框架来说,简直就是灾难。每个子系统里都要写点shiro的东西,慢慢的,越来越恶心。zuul网关就在这里大显身手了,控制用户的登录,鉴定用户的权限等等。zuul网关控制用户登录,鉴权以后再详说。
然后最近发现了另一个权限框架jcasbin
github地址:https://github.com/casbin/jcasbin

点击此处了解spring security权限控制使用操作

1.2 工作原理

1.2.1 PERM模型

Casbin 中, 访问控制模型被抽象为基于 PERM (Policy, Effect, Request, Matcher) 的一个文件,描述了资源与用户之间的关系。
PERM :

  • Policy:策略,定义权限的规则, p = {sub, obj, act, eft},策略一般存储到数据库,因为会有很多。
  • Effect:影响,它决定我们是否可以放行。
  • Request:访问请求, r = {sub, obj, act}。它实际上定义了我们应该提供访问控制匹配功能的参数名称和顺序。
    sub, obj, act, eft含义如下:
    • subsubject,访问实体;
    • objobject,访问的资源;
    • actaction,访问方法;
    • efteffect,策略结果,一般为空,默认指定allow,还可以定义为deny
  • Matcher:匹配规则,判断 Request 是否满足 Policy。

1.2.2 Model语法

ModelCasbin的具体访问模型,其主要以文件的形式出现,该文件常常以.conf最为后缀。

Model CONF 至少应包含四个部分: [request_definition], [policy_definition], [policy_effect], [matchers]
如果 model 使用 RBAC, 还需要添加[role_definition]部分。
Model CONF 文件可以包含注释。注释以 #开头, # 会注释该行剩余部分。

1.2.2.1 Request定义

[request_definition]
r = sub, obj, act

[request_definition] 部分用于request的定义,它明确了 e.Enforce(…) 函数中参数的含义。sub, obj, act 表示经典三元组: 访问实体 (Subject),访问资源 (Object) 和访问方法 (Action)

1.2.2.2 Policy定义

[policy_definition]
p = sub, obj, act

[policy_definition] 部分是对policy的定义,policy部分的每一行称之为一个策略规则, 每条策略规则通常以形如p, p2的policy type开头。

1.2.2.3 Policy effect定义

[policy_effect]
e = some(where (p.eft == allow))

[policy_definition] 部分是对policy的定义。上面的策略效果表示如果有任何匹配的策略规则 允许,最终效果是允许 (aka allow-override)
p.eft 是策略的效果,它可以 允许 或 否定。 它是可选的,默认值是 允许。 因为我们没有在上面指定它,所以它使用默认值。
在这个表达式中,some 是一个关键字,表示策略中是否存在符合后续条件的策略项。where 是一个关键字,用于指定条件。eft 属性表示策略的效果,通常用于表示允许访问。

1.2.2.4 角色定义

[role_definition]
g = _, _

这个部分定义了角色的结构
g = _, _ 表示角色使用通配符 _ 表示,表示不关心角色的具体值

1.2.2.5 匹配器

[matchers] 是策略匹配程序的定义。匹配程序是表达式。它定义了如何根据请求评估策略规则。

[matchers]
m = g(r.sub,p.sub) && r.obj == p.obj && r.act == p.act

上述匹配器是最简单的,这意味着请求中的主题、对象和行动应该与政策规则中的匹配。

  • g(r.sub, p.sub):表示通过匹配器函数 g 来匹配主体属性 r.sub 和策略项的主体属性 p.sub。这里使用的是通配符 “_”,表示不关心具体的角色值。
  • r.obj == p.obj:表示匹配对象属性,要求请求的对象属性 r.obj 和策略项的对象属性 p.obj 相等。
  • r.act == p.act:表示匹配动作属性,要求请求的动作属性 r.act 和策略项的动作属性 p.act 相等。

注意:g()函数和==运算符在匹配器中有不同的作用。

  • g(r.sub, p.sub)g()函数是一个特殊的函数,用于在匹配器中进行角色匹配。在这里,g()函数将匹配请求中的主体属性(r.sub)和策略项中的主体属性(p.sub)。这里的g()函数可以根据需求进行定制,例如使用角色继承关系等。通常情况下,使用通配符_来表示不关心角色的具体值。
  • r.obj == p.obj和r.act == p.act==是相等比较运算符,用于比较请求中的对象属性(r.obj)和策略项中的对象属性(p.obj),以及请求中的动作属性(r.act)和策略项中的动作属性(p.act)。它们要求两边的操作数在值上完全相等才会返回true。
  • g() 函数用于角色匹配,而==运算符用于属性值的比较。这两者在匹配器中的作用是不同的

1.2.2.6 完整model.conf

# Request定义
[request_definition]
r = sub, obj, act

# 策略定义
[policy_definition]
p = sub, obj, act

# 角色定义
[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

# 匹配器定义
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

1.2.3 policy.csv

policy.csv文件就相当于一张权限表。

p, zhangsan, data1, read

1.3 准备

1.3.1 mavan依赖

<dependency>
    <groupId>org.casbin</groupId>
    <artifactId>jcasbin</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>org.casbin</groupId>
    <artifactId>jdbc-adapter</artifactId>
    <version>2.0.0</version>
</dependency>

1.3.2 配置文件

jcasbin把用户的角色、权限信息(访问路径)放置在配置文件里,然后通过输入流读取配置文件。主要有两个配置文件:model.conf 和 policy.csv。
在这里插入图片描述
其实也可以读取数据库的角色权限配置。所以我们可以把关于数据库的信息提取出来,可以进行动态设置。

@Configuration
@ConfigurationProperties(prefix = "org.jcasbin")
public class EnforcerConfigProperties {
 
  private String url;
  
  private String driverClassName;
  
  private String username;
  
  private String password;
  
  private String modelPath;
 
}

这样我们就可以在application.properties里进行相关配置了。model.conf是固定的文件。policy.csv的内容是可以从数据库读取的。

org.jcasbin.url=jdbc:mysql://localhost:3306/casbin?useSSL=false
org.jcasbin.driver-class-name=com.mysql.cj.jdbc.Driver
org.jcasbin.username=root
org.jcasbin.password=root
# 绝对路径
org.jcasbin.model-path=D:/Work/Project/IDEAWorkSpace/idea2023/swagger-api-demo/conf/authz_model.conf
# 绝对路径
org.jcasbin.policy-path=D:/Work/Project/IDEAWorkSpace/idea2023/swagger-api-demo/conf/policy.csv

1.2.3 读取权限信息进行初始化

我们要对 Enforcer 这个类初始化,加载配置文件里的信息。所以我们写一个类实现InitializingBean,在容器加载的时候就初始化这个类,方便后续的使用。

@Component
public class EnforcerFactory implements InitializingBean {
 
  private static Enforcer enforcer;
 
  @Autowired
  private EnforcerConfigProperties enforcerConfigProperties;
  private static EnforcerConfigProperties config;
  
  @Override
  public void afterPropertiesSet() throws Exception {
    config = enforcerConfigProperties;
    //从数据库读取策略
    //JDBCAdapter jdbcAdapter = new JDBCAdapter(config.getDriverClassName(),config.getUrl(),config.getUsername(),config.getPassword());
    //enforcer = new Enforcer(config.getModelPath(), jdbcAdapter);
    //从配置文件读取策略
    enforcer = new Enforcer(config.getModelPath(), config.getPolicyPath());
    enforcer.loadPolicy();//Load the policy from DB.
  }
  
  /**
   * 添加权限
   * @param policy
   * @return
   */
  public static boolean addPolicy(Policy policy){
    boolean addPolicy = enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct());
    enforcer.savePolicy();
    
    return addPolicy;
  }
  
  /**
   * 删除权限
   * @param policy
   * @return
   */
  public static boolean removePolicy(Policy policy){
    boolean removePolicy = enforcer.removePolicy(policy.getSub(),policy.getObj(),policy.getAct());
    enforcer.savePolicy();
    
    return removePolicy;
  }
  
  public static Enforcer getEnforcer(){
    return enforcer;
  }
  
}

在这个类里,我们注入写好的配置类,然后转为静态的,在afterPropertiesSet方法里实例化Enforcer并加载policy(策略,角色权限/url对应关系)。

同时又写了两个方法,用来添加和删除policy,Policy是自定的一个类,对官方使用的集合/数组进行了封装。

public class Policy {
  /**想要访问资源的用户 或者角色*/
  private String sub;
  
  /**将要访问的资源,可以使用 * 作为通配符,例如/user/* */
  private String obj;
  
  /**用户对资源执行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用 * 作为通配符*/
  private String act;
 
}

1.4 使用

1.4.1 权限控制

jcasbin的权限控制非常简单,自定义一个过滤器,if判断就可以搞定,没错,就这么简单。

@WebFilter(urlPatterns = "/*" , filterName = "JCasbinAuthzFilter")
@Order(Ordered.HIGHEST_PRECEDENCE)//执行顺序,最高级别最先执行,int从小到大
public class JCasbinAuthzFilter implements Filter {
  
  private static final Logger log = LoggerFactory.getLogger(JCasbinAuthzFilter.class);
 
  private static Enforcer enforcer;
 
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
  }
 
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        
        String user = request.getParameter("username");
        String path = request.getRequestURI();
        String method = request.getMethod();
 
        enforcer = EnforcerFactory.getEnforcer();
        if (path.contains("anon")) {
          chain.doFilter(request, response);
    }else if (enforcer.enforce(user, path, method)) {
      chain.doFilter(request, response);
    } else {
      log.info("无权访问");
      Map<String, Object> result = new HashMap<String, Object>();
            result.put("code", "1001");
            result.put("msg", "用户权限不足");
            result.put("data",null);
            response.setCharacterEncoding("UTF-8");
            response.setContentType(application/json);
            response.getWriter().write(JSONObject.toJSONString(result,SerializerFeature.WriteMapNullValue));
      }
    
  }
 
  @Override
  public void destroy() {
    
  }
 
}

主要是用 enforcer.enforce(user, path, method) 这个方法对用户、访问资源、方式进行匹配。这里的逻辑可以根据自己的业务来实现。在这个过滤器之前还可以添加一个判断用户是否登录的过滤器。

1.4.2 添加删除权限

对于权限的操作,直接调用上面写好的 EnforcerFactory 里对应的方法即可。并且,可以达到同步的效果。就是不用重启服务器或者其他任何操作,添加或删除用户权限后,用户对应的访问就会收到影响。


@RestController
public class PerController {

    @PutMapping("/anon/role/per")
    public String addPer(){
        EnforcerFactory.addPolicy(new Policy("alice", "/user/list", "*"));
        return "OK";
    }

    @DeleteMapping("/anon/role/per")
    public String deletePer(){
        EnforcerFactory.removePolicy(new Policy("alice", "/user/list", "*"));
        return "OK";
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Server - PyTorch BFloat16 “TypeError: Got unsupported ScalarType BFloat16“ 解决方案

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132665807 BFloat16 类型是 16 位的浮点数格式&#xff0c;可以用来加速深度学习的计算和存储。BFloat16 类型的特点是保留 32 位浮点数&#xff…

龙智携手Atlassian和JFrog举办线下研讨会,探讨如何提升企业级开发效率与质量

2023年9月8日&#xff0c;龙智将携手Atlassian和JFrog于上海举办线下研讨会&#xff0c;以“大规模开发创新&#xff1a;如何提升企业级开发效率与质量”为主题&#xff0c;邀请龙智高级咨询顾问、Atlassian认证专家叶燕秀&#xff0c;紫龙游戏上海研发中心高级项目管理主管叶凯…

PHP8创建数组-PHP8知识详解

在php 8中&#xff0c;您可以使用以下方法创建数组&#xff1a;使用数组字面量创建数组、使用 array() 函数创建数组、通过赋值的方式创建数组、使用array_push()函数将元素添加到数组末尾、使用range()函数创建数值数组、使用compact()函数创建带有变量名的数组、使用array_fi…

C++ | 程序暂停功能

C | 程序暂停功能 文章目录 C | 程序暂停功能初衷rosbag 播包暂停功能源码 识别键盘输入&#xff08;需输入Enter&#xff09;识别键盘输入&#xff08;无需输入Enter&#xff09;opencv waitKey函数kill 信号包装成空格命令 Reference[C/C 获取键盘事件](https://www.runoob.c…

电动汽车电机驱动系统的组成和作用

1.电机驱动系统的作用与组成电动汽车电机驱动系统是新能源汽车的核心技术之一&#xff0c;它的主要任务是按驾驶员的驾驶意图&#xff0c;将动力电池的化学能高效地转化为机械能&#xff0c;经过变速器、驱动轴等机构驱动车轮。电动机驱动系统主要有电动机、功率器件和控制系统…

旅游APP外包开发注意事项

旅游类APP通常具有多种功能&#xff0c;以提供给用户更好的旅行体验。以下分享常见的旅游类APP功能以及在开发和使用这些APP时需要注意的问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 常见功能…

C++智能指针之shared_ptr(保姆级教学)

目录 C智能指针之shared_ptr 本文涉及所有程序 工作原理 使用方法 手动初始化 std::make_shared函数&#xff08;C14提出&#xff09; 构造方法初始化 make_shared初始化 使用实例 shared_ptr常规操作 use_count(); unique(); reset(); get(); 指定删除器 移动…

确保浏览安全:使用SSH实施加密SOCKS5

在互联网上保护隐私和安全至关重要。使用SSH&#xff08;Secure Shell&#xff09;创建加密的SOCKS5代理是一种简单且有效的方法&#xff0c;可以确保您的网络流量在传输过程中受到保护。本文将向您介绍如何使用SSH实施加密SOCKS5&#xff0c;以提高您的浏览安全。 1、准备工作…

使用perf_analyzer和model-analyzer测试tritonserver的模型性能超详细完整版

导读 当我们在使用tritonserver部署模型之后&#xff0c;通常需要测试一下模型的服务QPS的能力&#xff0c;也就是1s我们的模型能处理多少的请求&#xff0c;也被称为吞吐量。 测试tritonserver模型服务的QPS通常有两种方法&#xff0c;一种是使用perf_analyzer 来测试&#…

递归/回溯/动规

1 动规-打家劫舍一 你是一个经验丰富的小偷&#xff0c;准备偷沿街的一排房间&#xff0c;每个房间都存有一定的现金&#xff0c;为了防止被发现&#xff0c;你不能偷相邻的两家&#xff0c;即&#xff0c;如果偷了第一家&#xff0c;就不能再偷第二家&#xff1b;如果偷了第二…

计算机竞赛 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

Dubbo2.0

前置 衡量网站性能指标&#xff1a; 响应时间&#xff1a;一次请求花费时间并发数&#xff1a;同时处理请求数 并发连接数&#xff1a;每秒建立总TCP数量请求数&#xff1a;QPS一秒请求数并发用户数&#xff1a;单位时间用户 吞吐量&#xff1a;单位时间处理请求数 QPS&#…

Web前端自动化测试Cypress实践总结

本文主要首先主要介绍了什么是自动化测试&#xff0c;接着对常用的自动化测试框架进行了对比分析&#xff0c;最后&#xff0c;介绍了如果将自动化测试框架Cypress运用在项目中。 一、自动化测试概述 为了保障软件质量&#xff0c;并减少重复性的测试工作&#xff0c;自动化测…

GaussDB数据库SQL系列-层次递归查询

目录 一、前言 二、GuassDB数据库层次递归查询概念 三、GaussDB数据库层次递归查询实验示例 1、创建实验表 2、sys_connect_by_path(col, separator) 3、connect_by_root(col) 4、WITH RECURSIVE 四、递归查询的优缺点 1、优点 2、缺点 五、总结 一、前言 层次递归…

中使用pack局管理器:管理器布置小部件

一、说明 在本教程中&#xff0c;我们将了解如何制作登录 UI。今天的教程将重点介绍如何使用 Tkinter 的pack布局管理器。 二、设计用户界面 什么是布局管理器&#xff1f;创建图形界面时&#xff0c;窗口中的小部件必须具有相对于彼此排列的方式。例如&#xff0c;可以使用微件…

Yolov5的tensorRT加速(python)

地址&#xff1a;https://github.com/wang-xinyu/tensorrtx/tree/master/yolov5 下载yolov5代码 方法一&#xff1a;使用torch2trt 安装torch2trt与tensorRT 参考博客&#xff1a;https://blog.csdn.net/dou3516/article/details/124538557 先从github拉取torch2trt源码 ht…

【C++ 二叉搜索树】

目录 1.什么是二叉搜索树2.构建二叉搜索树2.1首先搭建树的框架2.2搭建搜索树的框架 3.二叉搜索树的插入3.1非递归式插入3.2递归式插入 4.二叉搜索树的查找4.1非递归查找4.2递归查找 5.二叉搜索树的删除5.1非递归删除5.2递归删除 6.整个代码实现 1.什么是二叉搜索树 简单来讲就…

WebDAV之π-Disk派盘 + 小书匠

小书匠是一款功能丰富,强大的知识管理工具。全平台覆盖,离线数据存储,自定义数据服务器,所见即所得的 markdown 编辑体验。 小书匠提供了多种实用的编辑模式,例如:栏编辑、双栏编辑、三栏编辑、全屏写作、全屏阅读等。并且该软件还提供了许多有用的扩展语法,比如Latex公…

【前端demo】CSVJSON转换器 原生实现:CSV转换为JSON,JSON转换为CSV

文章目录 效果过程textareaTooltip提示工具按钮的min-width判断输入是否是CSV或JSONJSON与CSV样例JSON转为CSVCSV转为JSON不足之处 代码HTMLCSSJS 其他demo 效果 效果预览&#xff1a;CSV&JSON Converter (codepen.io) 参照的预览&#xff1a;JSV Converter(gpaiva00.git…

地毯16 CFR 1630/1631安全防火性易燃性测试

地毯的16 CFR 1630/1631安全防火性易燃性测试是一项重要的产品检测认证标准。该测试旨在评估地毯材料的防火性能&#xff0c;以确保其在使用过程中不会引发火灾或加剧火势。测试过程包括对地毯样品进行燃烧测试和燃烧后的评估。 根据16 CFR 1630标准&#xff0c;地毯样品将被暴…