权限管理系统数据库设计的简单构思

最近在工作中接触到权限管理的设计,于是,自己在网上查阅了部分资料,再加上自己的一些思考,构思了一个简单的权限管理系统的数据库设计。

RBAC与Tag

说到权限管理,一般都会想到基于角色的访问控制(Role-Based Access Control,RBAC)
百度百科:http://baike.baidu.com/link?url=9Rt_oq7oAbT7fPGR4E8oPfZ-GVIJ2BXcb3AviQuFC1Z7eqXWb3W02mzJPl8aJJyQ4R-gyPjIBNFLORKYjMND_K
维基百科:https://en.wikipedia.org/wiki/Role-based_access_control

但是以我个人的理解,基于Role的角色控制有时会显得不够灵活。在实际生产中,大部分使用访问都是基于角色的,但是也会出现以特殊权限的非角色的访问。
例如一个仓库,平时只有总经理和董事长有权访问,现在,消防部门派了A过来做安全检查,此时,我们就需要为A临时增加访问仓库的特殊权限,此时A对于公司的Role就很难定义了。
所以,这里我用tag代替role,变成Tag-Based Access Control,即基于标签的访问控制。tag可以是某一个角色,也可以是某一个用户组,甚至可以是任意一种标志,所有的权限都是基于tag进行授权。
再回到上面那个例子,对于总经理和董事长,我们有”总经理”和”董事长”的tag,对于消防检查的A,我们可以临时增加”消防检查”的tag,等检查结束,就可以删除”消防检查”tag.
这里,我思考了一般权限管理系统的三种使用情况:访问url的权限管理,访问数据表的权限管理,访问数据的权限管理。


访问url的权限管理

权限管理系统数据库设计的简单构思_第1张图片

user与tag通过user_tag中间表建立关系,形成一对多的关系,一个user可能具有多个tag,而tag可以代表任何标志,例如角色或者角色组,即tag是role的进化。tag与url通过tag_url表建立关系,tag与url同样是一对多的关系,即一个标签有权访问一个或多个url。tag_url表其实就是权限控制表,permission字段代表访问权限,是一个bool字段,true表示有权访问,false表示无权访问。
当然,这里的url其实就是action,即对于user来说的任何动作。

对应的表结构:

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50721
Source Host           : localhost:3306
Source Database       : bestpractice

Target Server Type    : MYSQL
Target Server Version : 50721
File Encoding         : 65001

Date: 2018-05-29 22:10:01
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for tag
-- ----------------------------
DROP TABLE IF EXISTS `tag`;
CREATE TABLE `tag` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tag` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for tag_url
-- ----------------------------
DROP TABLE IF EXISTS `tag_url`;
CREATE TABLE `tag_url` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tag_id` int(11) NOT NULL,
  `url_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for url
-- ----------------------------
DROP TABLE IF EXISTS `url`;
CREATE TABLE `url` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for user_tag
-- ----------------------------
DROP TABLE IF EXISTS `user_tag`;
CREATE TABLE `user_tag` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

访问资源resource的权限管理

在一些系统中,进行权限管理的并不是url,而是某一些资源resource,权限也从true(有权访问)或false(无权访问),变成了crud(增删改查)四个bool字段,这时只要相应的修改tag与resource的中间表,即权限控制表即可。
权限管理系统数据库设计的简单构思_第2张图片


访问特定记录record的权限管理

访问资源resource的权限管理中的curd是对整张表的权限控制,但是,实例生成中还存在对表中特定数据的权限管理问题。
例如对于某个用户,他只能查询表中的某些记录,而对另外的记录则无权访问。
一般,我们查询特定记录的sql为:

SELECT * FROM record where id > 10 AND id < 20;

同理,我们可以为权限控制表加入where_condition字段,类型时varchar,用于保存查询条件。
权限管理系统数据库设计的简单构思_第3张图片
这样,就可以灵活的控制具有指定标签tag的用户user对特定记录record的访问控制。


前端

在具有权限控制的系统中,前端界面往往要根据不同身份的人作出相应的调整,例如一个按钮,对于某个身份的人应该显示,对于另外一种身份的人应该隐藏,因为他无权访问操作这个按钮代表的动作。
那前端界面应该怎么写呢?
如果使用后台渲染,例如java的jsp,.net的razor,这样虽然可以通过后台代码生成指定的HTML,但是在稍微复杂的系统中,需要在渲染页面写大量的后台代码,大量的逻辑判断if/else,而且前后端不分离,越到后面越难扩展维护。
我个人的看法是可以使用前端的HTML标签自定义属性。

<a href="http://www.xxx.com" style="display:none;" TagAccessControl="访问敏感信息" >访问敏感信息a>

TagAccessControl是我们自定义标签属性,访问敏感信息为只有特定权限的人才能访问的页面,URL为http://www.xxx.comstyle="display:none;"a标签的默认属性是隐藏,然后通过ajax将权限控制的相关信息通过js变量输出到前端,通过js的一个for循环,将html中所有具有TagAccessControl属性的dom元素进行js操作,如果具有访问权限的,则将style="display:none;"去掉,使dom元素可见。一个控件从可见到不可见对用户来说是很难接受的,但是从不可见到可见,对用户来说是可以接受的。
不过此时,用户无权访问的dom元素只是在隐藏而已,出于安全考虑,避免有些不怀好意的人通过某些方法,绕过前端,直接访问对应的URL,后台接口也要对每一次访问的用户进行权限判断,可以将controller继承basecontroller,然后在basecontroller统一对用户访问行为进行过滤,也可以通过自定义属性的方式,在自定义属性里做权限过滤。

一般权限管理系统都要有一个权限管理界面,网上有很多酷炫的开源前端框架,适合做管理界面。
AdminLTE:https://almsaeedstudio.com/themes/AdminLTE/index2.html
Xenon:http://www.jq22.com/demo/Bootstrap-150103222921/ui-widgets.html
Neon:http://themes.laborator.co/#theme=neon


总结

本人并无参与大型权限系统的开发,以上都是自己对权限管理系统数据库设计的简单构思,并没有在实例项目考验过,不过平时多思考多记录,当真的需要设计管理系统时,也会想的更全面,毕竟数据库设计是项目开发的地基,如果地基打的不够牢靠,建筑就会变得很难维护,甚至有倒塌的危险。

你可能感兴趣的:(数据库)