• golang、gin、gorm、casbin访问权限控制


    Casbin configuration

    rbac_model.conf

    [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
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. r = sub, obj, act defines that a limited request will consist of 3 parts: subject - user, object - URL or more generally resource and action - operation.

      定义请求,sub表示用户或角色,obj表示访问的资源,act表示动作读、写、POST、GET等。

    2. p = sub, obj, act defines the format of policy. For example, admin, data, write means All admins can write data.

      定义策略的格式。例如admin, data, write表示角色为admin的所有用户可以访问data,操作为写操作。

    3. e = some(where (p.eft == allow)) means that a user can do something as long as there is a defined policy which allows him to do so.

      表示策略结果至少有一个为allow则允许访问。

    4. g = _, _ defines the format of definition of user’s role. For example, Alice, admin indicates Alice is an admin.

      表示用户和角色的关系。例如Alice, admin表示Alice的角色是admin。

    5. m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act defines the workflow of authorization: check user’s role -> check the resource which user is trying to access -> check what user wants to do.

      匹配器。

    Policies

    Casbin策略文件可以存储在csv文件或者是数据库中,csv格式如下:

    p, user, resource, read
    p, username, resource, read
    p, admin, resource, read
    p, admin, resource, write
    g, alice, admin
    g, bob, user
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    存储数据库表结构如下:

    CREATE TABLE casbin_rule (
        p_type VARCHAR(100),
        v0 VARCHAR(100),
        v1 VARCHAR(100),
        v2 VARCHAR(100)
    );
    INSERT INTO casbin_rule VALUES('p', 'user', 'resource', 'read');
    INSERT INTO casbin_rule VALUES('p', 'username', 'resource', 'read');
    INSERT INTO casbin_rule VALUES('p', 'admin', 'resource', 'read');
    INSERT INTO casbin_rule VALUES('p', 'admin', 'resource', 'write');
    INSERT INTO casbin_rule(p_type, v0, v1) VALUES('g', 'alice', 'admin');
    INSERT INTO casbin_rule(p_type, v0, v1) VALUES('g', 'bob', 'user');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    golang权限控制

    github.com/casbin/gorm-adapter/v3
    gorm.io/gorm
    github.com/casbin/casbin/v2
    
    • 1
    • 2
    • 3
    // 验证每一个角色
    func CheckCasbinAuth() gin.HandlerFunc {
    	return func(c *gin.Context) {
    		requstUrl := c.Request.URL.Path
    		method := c.Request.Method
    		// 用户角色id需要存储在缓存,加快接口验证的效率(2021-03-11  后续实现)
    		orgIds := [1]int{} // 模拟用户角色
    		var roleId int
    		var isPass bool
    		var err error
            enforcer := casbin.NewEnforcer("config/rbac_model.conf", adapter)
            // 循环用户角色判断
    		for i := 0; i < len(orgIds); i++ {
    			roleId = orgIds[i]
    			isPass, err = enforcer.Enforce(strconv.Itoa(roleId), requstUrl, method)
    			if isPass == true {
    				break
    			}
    		}
    		if err != nil {
    			response.ErrorCasbinAuthFail(c, err.Error())
    			return
    		} else if !isPass {
    			response.ErrorCasbinAuthFail(c, "")
    		} else {
    			c.Next()
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    // 验证用户,casbin将会去策略数据里自动查找用户的角色(g, alice, admin),在根据角色验证访问权限
    func CheckCasbinAuth() gin.HandlerFunc {
    	return func(c *gin.Context) {
    		requstUrl := c.Request.URL.Path
    		method := c.Request.Method
            userId := "" // 从登录用户中获取用户ID
    		var isPass bool
    		var err error
            // 会根据用户ID(或者用户名)查找角色去验证权限
            enforcer := casbin.NewEnforcer("config/rbac_model.conf", adapter)
    		isPass, err = enforcer.Enforce(userId, requstUrl, method)
    		if err != nil {
    			response.ErrorCasbinAuthFail(c, err.Error())
    			return
    		} else if !isPass {
    			response.ErrorCasbinAuthFail(c, "")
    		} else {
    			c.Next()
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    数据结构与算法之美 复杂度分析(上)
    认识Modbus通信协议(笔记)
    idea 本地项目上传到 Git 步骤
    “知识图谱补全”术语:知识图谱补全、三元组分类、链接预测
    打开文件、文件夹权限的C++源码 (去掉禁用权限)
    自定义注解
    【Ubuntu】Anaconda的安装和使用
    14.mybatis拦截器原理
    RestTemplate使用InputStreamResource上传文件
    使用pytest+selenium编写网页UI自动化脚本和用例
  • 原文地址:https://blog.csdn.net/fggdgh/article/details/125512554