1. Casbin简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用文档

1.1Casbin 是什么?

  • Casbin 可以:
  1. 支持自定义请求的格式,默认的请求格式为{subject, object, action}。
  2. 具有访问控制模型model和策略policy两个核心概念。
  3. 支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
  4. 支持内置的超级用户 例如:root或administrator。超级用户可以执行任何操作而无需显式的权限声明。
  5. 支持多种内置的操作符,如 keyMatch,方便对路径式的资源进行管理,如 /foo/bar 可以映射到 /foo*
  • Casbin 不能:
  1. 身份认证 authentication(即验证用户的用户名、密码),casbin只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin进行访问控制,二者是相互配合的关系。
  2. 管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系。

1.2 API文档

2. Casbin使用

2.1 引入依赖

<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>

2.2 Model文件

支持的Models

  • ACL (Access Control List, 访问控制列表)
  • 具有 超级用户 的 ACL
  • 没有用户的 ACL: 对于没有身份验证或用户登录的系统尤其有用。
  • 没有资源的 ACL: 某些场景可能只针对资源的类型, 而不是单个资源, 诸如 write-article, read-log等权限。 它不控制对特定文章或日志的访问。
  • RBAC (基于角色的访问控制)
  • 支持资源角色的RBAC: 用户和资源可以同时具有角色 (或组)。
  • 支持域/租户的RBAC: 用户可以为不同的域/租户设置不同的角色集。
  • ABAC (基于属性的访问控制): 支持利用resource.Owner这种语法糖获取元素的属性。
  • RESTful: 支持路径, 如 /res/*, /res/: id 和 HTTP 方法, 如 GET, POST, PUT, DELETE。
  • 拒绝优先: 支持允许和拒绝授权, 拒绝优先于允许。
  • 优先级: 策略规则按照先后次序确定优先级,类似于防火墙规则。

权限校验将根据matchers进行校验,注意matchers写法,下面是一个具有超级管理员admin权限的Model文件。

[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  || r.sub == "admin"

RESTFu与RBAC共同使用

[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 = r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act) || g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)

2.3 Policy 文件

Policy文件可用使用scv文件,也可以使用JDBC数据库形式,详细参考

3. 使用方法

3.1 编写一个配置类,读取jdbc配置

@Data
@Configuration
@ConfigurationProperties(prefix = "org.jcasbin")
public class EnforcerConfigProperties {

  
   
    private String datasourceUrl;


    private String driverClassName;

    private String datasourceUserName;


    private String databasePassword;
 @Bean
    public JDBCAdapter jdbcAdapter() throws Exception {

        return new JDBCAdapter(driverClassName, datasourceUrl, datasourceUserName,databasePassword );
    }
}

配置文件 application.properties

org.jcasbin.url=jdbc:mysql://localhost:3306/test
org.jcasbin.driver-class-name=com.mysql.cj.jdbc.Driver
org.jcasbin.username=root
org.jcasbin.password=root

3.2 也可以使用springjdbc配置

@Configuration
@Slf4j
public class CasbinAdapterConfiguration {

    /**
     * datasourceUrl 连接数据库url
     */
    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    /**
     * driverClassName 数据库驱动
     */
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    /**
     * datasourceUserName 连接数据库的用户名
     */
    @Value("${spring.datasource.username}")
    private String datasourceUserName;

    /**
     * databasePassword 连接数据库密码
     */
    @Value("${spring.datasource.password}")
    private String databasePassword;

    @Bean
    public JDBCAdapter jdbcAdapter() throws Exception {

        return new JDBCAdapter(driverClassName, datasourceUrl, datasourceUserName,databasePassword );
    }
}


3.3 创建Policy

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Policy {

    /**
     * 想要访问资源的用户 或者角色
     */
    private String sub;

    /**
     * 将要访问的资源,可以使用  * 作为通配符,例如/user/*
     */
    private String obj;

    /**
     * 用户对资源执行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用 * 作为通配符
     */
    private String act;

}

3.4 创建Group

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Group {
    /**
     * 请求对象
     */
    private String rSub;

    /**
     * 策略对象
     */
    private String pSub;
}

3.5 创建一个EnforcerFactory

@Component
public class EnforcerFactory implements InitializingBean {

    private Enforcer enforcer;

    private EnforcerConfigProperties enforcerConfigProperties;

	private JDBCAdapter jdbcAdapter;

    @Autowired
    public EnforcerFactory(EnforcerConfigProperties enforcerConfigProperties,JDBCAdapter jdbcAdapter) {
        this.enforcerConfigProperties = enforcerConfigProperties;
         this.jdbcAdapter = jdbcAdapter;

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        enforcerConfigProperties = enforcerConfigProperties;
        //从数据库读取策略

        Model model = new Model();
        File file = new File("src/main/resources/conf/authz_model.conf");
        String canonicalPath = file.getCanonicalPath();
        model.loadModel(canonicalPath);

        enforcer = new Enforcer(model, jdbcAdapter);
    }

    /**
     * 添加权限
     *
     * @param policy
     * @return
     */
    public boolean addPolicy(Policy policy) {
        boolean addPolicy = enforcer.addPolicy(policy.getSub(), policy.getObj(), policy.getAct());
        enforcer.savePolicy();

        return addPolicy;
    }

    /**
     * 删除权限
     *
     * @param policy
     * @return
     */
    public boolean removePolicy(Policy policy) {
        boolean removePolicy = enforcer.removePolicy(policy.getSub(), policy.getObj(), policy.getAct());
        enforcer.savePolicy();
        return removePolicy;
    }

    public Enforcer getEnforcer() {
        return enforcer;
    }


}

3.6 自定义一个过滤器/拦截器

ublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("过滤器初始化");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String user = request.getParameter("username");
        String path = request.getRequestURI();
        String method = request.getMethod();

        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() {

    }

}

3.7 创建一个controller

@RestController
public class contorller {

    @Autowired
    private EnforcerFactory enforcerFactory;
    @GetMapping("/anon/test")
    public void Test(){
        enforcerFactory.addPolicy(new Policy("alice", "/test", "GET"));
    }

    @GetMapping("/test")
    public void test1(){
        System.out.println("通过");
    }

}

3.8 测试

4. CasbinAPI使用

5. demo下载

6.扩展

6.1 Model文件编辑测试

在这里插入图片描述

6.2 Springboot整合Jcasbin

casbin-spring-boot-starter源码,修改力度大,功能不完善,可参考

<!-- https://mvnrepository.com/artifact/org.casbin/casbin-spring-boot-starter -->
<dependency>
    <groupId>org.casbin</groupId>
    <artifactId>casbin-spring-boot-starter</artifactId>
    <version>0.0.11</version>
</dependency>

7. 常见问题

7.1 FileNotFoundException

springboot打成jar后,启动时抛出Caused by: java.io.FileNotFoundException: class path resource [model.conf] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/opt/fabric-apps/fabric-mgt/target/fabric-mgt.jar!/BOOT-INF/classes!/model.conf
解决方案

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐