zoukankan      html  css  js  c++  java
  • 数据权限限定办法

    /*
     Navicat Premium Data Transfer
    
     Source Server         : localhost
     Source Server Type    : MySQL
     Source Server Version : 100412
     Source Host           : localhost:22066
     Source Schema         : base_db
    
     Target Server Type    : MySQL
     Target Server Version : 100412
     File Encoding         : 65001
    
     Date: 15/03/2020 11:28:38
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for t_base_person_role
    -- ----------------------------
    DROP TABLE IF EXISTS `t_base_person_role`;
    CREATE TABLE `t_base_person_role`  (
      `person_role_id` int(11) NOT NULL COMMENT '主键ID',
      `identity_id` int(11) NOT NULL COMMENT '身份ID',
      `person_id` int(11) NOT NULL COMMENT '人员ID',
      `role_id` int(11) NOT NULL COMMENT '角色ID',
      `business_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '哪个省?哪个市?哪个县?哪个单位?哪个子单位?',
      `update_ts` datetime(0) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间戳',
      PRIMARY KEY (`person_role_id`) USING BTREE,
      UNIQUE INDEX `identity_id`(`identity_id`, `person_id`, `role_id`, `business_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_base_person_role
    -- ----------------------------
    
    -- ----------------------------
    -- Table structure for t_base_resource
    -- ----------------------------
    DROP TABLE IF EXISTS `t_base_resource`;
    CREATE TABLE `t_base_resource`  (
      `resource_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `resource_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源名称',
      `resource_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源代码',
      `resource_sql` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查找对应单位的SQL',
      `update_ts` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '最后更新时间戳',
      PRIMARY KEY (`resource_id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_base_resource
    -- ----------------------------
    INSERT INTO `t_base_resource` VALUES (1, '单位', 'bureau_id', 'select ? as bureau_id', '2020-03-15 11:27:48');
    INSERT INTO `t_base_resource` VALUES (2, '学校', 'school_id', 'select ? as bureau_id', '2020-03-15 11:28:08');
    INSERT INTO `t_base_resource` VALUES (3, '班级', 'class_id', 'select bureau_id from t_base_class where class_id=?', '2020-03-15 11:14:39');
    INSERT INTO `t_base_resource` VALUES (4, '部门', 'org_id', 'select bureau_id from t_base_organization where org_id=?', '2020-03-15 11:19:47');
    INSERT INTO `t_base_resource` VALUES (5, '教职工', 'teacher_id', 'select bureau_id from t_base_teacher where teacher_id=?', '2020-03-15 11:23:02');
    INSERT INTO `t_base_resource` VALUES (6, '学生', 'student_id', 'select bureau_id from t_base_student where student_id=?', '2020-03-15 11:20:34');
    INSERT INTO `t_base_resource` VALUES (7, '家长', 'parent_id', 'select bureau_id from t_base_parent where parent_id=?', '2020-03-15 11:20:53');
    
    -- ----------------------------
    -- Table structure for t_base_role
    -- ----------------------------
    DROP TABLE IF EXISTS `t_base_role`;
    CREATE TABLE `t_base_role`  (
      `role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
      `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
      `distribute_able` int(255) NOT NULL DEFAULT 1 COMMENT '是否可以分配给真实的人员',
      `update_ts` datetime(0) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间戳',
      PRIMARY KEY (`role_id`) USING BTREE,
      INDEX `distribute_able`(`distribute_able`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '(1)此角色表是基础数据内置的角色表,不是为共享给其它系统的公用概念,与分管工作有本质的区别。
    (2)有指定角色的人员,不管是真实的人员,还是系统虚拟的管理人员,都需要在指定角色时配置数据范围,即哪个市,哪个校,哪个区,哪个单位
    (3)系统管理员是不能二次分配给真实人员的。
    (4)除系统管理员外,其它管理员角色是不可分配给真实人员的。' ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_base_role
    -- ----------------------------
    INSERT INTO `t_base_role` VALUES (1, '系统管理员', 0, '2020-03-15 10:11:43');
    INSERT INTO `t_base_role` VALUES (2, '省管理员', 1, '2020-03-15 10:11:43');
    INSERT INTO `t_base_role` VALUES (3, '市管理员', 1, '2020-03-15 10:11:43');
    INSERT INTO `t_base_role` VALUES (4, '县区管理员', 1, '2020-03-15 10:11:43');
    INSERT INTO `t_base_role` VALUES (5, '单位管理员', 1, '2020-03-15 10:11:43');
    INSERT INTO `t_base_role` VALUES (6, '分校(教学点)管理员', 1, '2020-03-15 10:11:43');
    
    -- ----------------------------
    -- Table structure for t_sys_identity
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_identity`;
    CREATE TABLE `t_sys_identity`  (
      `identity_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '身份ID',
      `identity_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '身份名称',
      `exposed` int(255) NOT NULL DEFAULT 1 COMMENT '其它系统是否可见',
      `update_ts` datetime(0) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间戳',
      PRIMARY KEY (`identity_id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_sys_identity
    -- ----------------------------
    INSERT INTO `t_sys_identity` VALUES (1, '系统管理员', 0, '2020-03-15 10:13:10');
    INSERT INTO `t_sys_identity` VALUES (2, '教职工', 1, '2020-03-15 10:13:10');
    INSERT INTO `t_sys_identity` VALUES (3, '学生', 1, '2020-03-15 10:13:10');
    INSERT INTO `t_sys_identity` VALUES (4, '家长', 1, '2020-03-15 10:13:10');
    
    -- ----------------------------
    -- Table structure for t_sys_loginperson
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_loginperson`;
    CREATE TABLE `t_sys_loginperson`  (
      `login_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
      `login_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录名',
      `person_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
      `pwd` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
      `salt` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '盐',
      `identity_id` int(11) NOT NULL COMMENT '身份ID',
      `person_id` int(11) NOT NULL COMMENT '人员ID',
      `update_ts` datetime(0) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间戳',
      PRIMARY KEY (`login_id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_sys_loginperson
    -- ----------------------------
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    2、利用swagger的注释进行角色访问权限控制

    // PingExample godoc
    // @Summary 获取一条数据记录的示例
    // @Description 获取一条数据记录的示例
    // @Tags 获取一条数据记录的示例
    // @Accept json
    // @Param id query int true "单条记录的id"
    // @Produce json
    // @Success 200 {string} string "pong"
    // @Router /shortcutkey/SelectSingle [get]
    // @X-Role-Resource {"role_id":[1,2,3,4,5],"resource_id":1}
    
    最后这一句是有用的,描述了哪些角色可以使用这个接口,本接口相关的是哪类资源。
    

    3、每次构建前

    swag init
    

    4、初始化拦截器检查列表

    //读取doc目录下的swagger.json
    	f, err := os.Open("./docs/swagger.json")
    	if err != nil {
    		fmt.Println("读取swagger.json失败!")
    		return
    	}
    	content, _ := ioutil.ReadAll(f)
    	var inter interface{}
    	err = json.Unmarshal(content, &inter)
    	if err != nil {
    		fmt.Println("ERROR: ", err.Error())
    		return
    	}
    	var xRoleResource map[string]interface{}
    	m := inter.(map[string]interface{})
    	n := m["paths"].(map[string]interface{})
    	for k,v := range n {
    		t:=v.(map[string]interface{})
    		if t["get"]!=nil{
    			d:=t["get"].(map[string]interface{})
    			xRoleResource =d["x-role-resource"].(map[string]interface{})
    		}
    		if t["post"]!=nil{
    			p:=t["post"].(map[string]interface{})
    			xRoleResource =p["x-role-resource"].(map[string]interface{})
    		}
    		fmt.Println("接口地址:"+k)
    		fmt.Println("使用的资源ID:"+fmt.Sprintf("%d", int(xRoleResource["resource_id"].(float64))))
    		t1:=xRoleResource["role_id"].([]interface{})
    		for i := 0; i < len(t1); i++ {
    			fmt.Print(int(t1[i].(float64)), "	")
    		}
    	}
    
    

    5、在拦截器中进行拦截检查

    1、根据cookie中的加密串,解密还原为identity_id和person_id.
    2、根据identity_id+person_id查询t_base_person_role,获取到role_id,business_id(可能是省市县,单位,子单位),考虑性能,可以读取一次后保存到缓存中,有TTL值,比如10分钟。
    3、根据swagger的解析json,可以知道当前拦截的接口是哪个,需要拦截的resource_id是什么,限定的role_id有哪些。
    4、根据统一获取的bureau_id,通过一个通用接口,获取单位的省市县,单位,子单位等一系列值,考虑到性能,可以上基础数据开发人员提供,在维护更新单位时一并删除缓存即可。
    5、两组数据进行交叉对比,存在交集表示可以操作,否则是没有权限操作此接口,挡回。
    

    6、总结

    (1)此设计对整体系统要有控制权,每一个环节必须按要求开发,比如统一的bureau_id参数。
    (2)此设计无通用性,只能是一种思路。
    (3)性能上可以通过缓存等方式进行减压,并发也没有关系。
    (4) 每个系统,需要有独立的mysql用户帐号,不能都统一用root,基础数据也不能使用root,因为一旦被暴库,可能全面有被删除数据的风险,使用权限低的mysql帐号,可以限定操作权只在自己的数据库内,不会损坏其它系统的数据,这个确实非常重要。

  • 相关阅读:
    我们如何监视所有 Spring Boot 微服务?
    如何使用 Spring Boot 实现异常处理?
    如何使用 Spring Boot 实现分页和排序?
    如何集成 Spring Boot 和 ActiveMQ?
    如何实现 Spring Boot 应用程序的安全性?
    Spring Boot 中的监视器是什么?
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    Spring 和 SpringBoot 有什么不同?
    Spring Boot 有哪些优点?
    如何在不使用BasePACKAGE过滤器的情况下排除程序包?
  • 原文地址:https://www.cnblogs.com/littlehb/p/12492302.html
Copyright © 2011-2022 走看看