权限框架Shiro学习之表结构设计mysql
Shiro是一款优秀的开源安全框架,学习Shiro你们能够参考张开涛老师的博客:跟我学Shiro,固然也可参考我以前的笔记:Shiro实现身份认证、Shiro实现受权。git
在学习完基础的Shiro入门知识,咱们能够动手写一个小Demo了,此次咱们将以一个用户-角色-权限管理的Demo来进一步学习Shiro。github
<!--more-->sql
开发用户-角色-权限管理系统,首先咱们须要知道用户-角色-权限
管理系统的表结构设计。数据库
在用户-角色-权限
管理系统找那个通常会涉及5张表,分别为:后端
sys_users
用户表sys_roles
角色表sys_permissions
权限表(或资源表)sys_users_roles
用户-角色关联表sys_roles_permissions
角色-权限关联表(或角色-资源关联表)详细的建表信息以下安全
sys_users
解释 用户表中至少包含以上的字段,主键id、用户名username、密码password、盐值salt(由于密码是通过Shiro加密的,须要经过盐值校验,由Shiro生成,不须要用户手动填写)、角色列表roleId(这个字段不是必须的,仅实如今展现用户信息的时候能同时展现用户当前角色)、是否锁定locked(决定当前帐户是不是锁定的)。 建立新的用户,仅须要输入用户名和密码便可,盐值由Shiro生成,角色列表和是否锁定均可以在后期管理。框架
其中是否锁定字段类型为tinyint(1)
,设置这种类型,数据库中实际存储的是int类型数据,通常是0和1,在使用Mybatis取这个字段的数据时,Mybatis会自动将tinyint(1)
字段值为0的转换成false,将字段值为1以上的转换为true。学习
sys_roles
解释 角色表中role角色名称通常为存储着相似user:create
这种格式,Shiro在Realm中校验用户身份的时候会经过role
这个字段值进行校验;description
是此角色的描述信息,好比用户建立
。 其中pid
表示父节点,就是说,当前的角色可能有上级节点,好比老师
,这个角色可能就有父节点计科教师
,若是存在父节点,这个字段值就是父级节点的ID,根据这个ID,在展现数据的时候就很方便的展现出其在哪一个父节点下。 available
表示当前节点是否锁定,一样是tinyint(1)
类型,若是为false就说明没有锁定。this
sys_users_roles
解释 用户角色表就比较简单了,仅仅包含了主键id
、用户IDuser_id
、角色IDrole_id
;这张表主要描述指定用户与角色间的依赖关系。其中用户表与角色表是一对多的关系,一个用户能够拥有多个角色。
sys_permissions
解释 权限表和角色表相似,其中不一样的字段是rid
,这个字段表示此权限关联的角色的id值,固然不是必要的,可是后端角色更新时用到了,后面会介绍。
sys_roles_permissions
解释 角色-权限表和用户-角色表相似,包含了主键id
、角色IDrole_id
、权限IDpermission_id
,主要描述角色和权限间的依赖关系,一样,角色和权限间也是一对多的关系,一个角色会关联多个权限。
<br/>
上述表设计的源码以下:
-- create database shiro default character set utf8; drop table if exists sys_users; drop table if exists sys_roles; drop table if exists sys_permissions; drop table if exists sys_users_roles; drop table if exists sys_roles_permissions; create table sys_users ( id bigint auto_increment comment '编号', username varchar(100) comment '用户名', password varchar(100) comment '密码', salt varchar(100) comment '盐值', role_id varchar(50) comment '角色列表', locked bool default false comment '是否锁定', constraint pk_sys_users primary key(id) ) charset=utf8 ENGINE=InnoDB; create unique index idx_sys_users_username on sys_users(username); create table sys_roles ( id bigint auto_increment comment '角色编号', role varchar(100) comment '角色名称', description varchar(100) comment '角色描述', pid bigint comment '父节点', available bool default false comment '是否锁定', constraint pk_sys_roles primary key(id) ) charset=utf8 ENGINE=InnoDB; create unique index idx_sys_roles_role on sys_roles(role); create table sys_permissions ( id bigint auto_increment comment '编号', permission varchar(100) comment '权限编号', description varchar(100) comment '权限描述', rid bigint comment '此权限关联角色的id', available bool default false comment '是否锁定', constraint pk_sys_permissions primary key(id) ) charset=utf8 ENGINE=InnoDB; create unique index idx_sys_permissions_permission on sys_permissions(permission); create table sys_users_roles ( id bigint auto_increment comment '编号', user_id bigint comment '用户编号', role_id bigint comment '角色编号', constraint pk_sys_users_roles primary key(id) ) charset=utf8 ENGINE=InnoDB; create table sys_roles_permissions ( id bigint auto_increment comment '编号', role_id bigint comment '角色编号', permission_id bigint comment '权限编号', constraint pk_sys_roles_permissions primary key(id) ) charset=utf8 ENGINE=InnoDB;
上面就是当前用户-角色-权限
系统的表设计。细心的你可能会发现这些表中并不包含外键约束。
为何不设计外键呢?
可能你会跟我同样有这样的疑问。好比用户表和角色表间,咱们这里建立了用户-角色表来实现二者的关联;并无经过给两张表创建外键来实现一对多、多对多的关联关系。 由于若是你要创建外键来关联两张表,你须要遇到以下:
一
的一方新增数据的时候,你要考虑多
的一方是否存在指定的id。多
的一方时你要先删除其关联的一
的一方,再删除多
的一方。也就是说若是使用了外键关联,那么在对表进行数据操做时就必须考虑另外一张关联的表,至关于两张表就绑在一块儿了,操做这张表就必须考虑另外一张关联表。
可是实际中,咱们不想当即就修改或更新关联表的数据,我可能一会再去更新另外一张关联表的数据,那么就产生了这种方式:经过单独创建一张关联来实现两张表的数据关联。
因此,我建议你们在设计表时尽可能减小表与表直接的外键约束,这样能避免不少麻烦,而且两张表之间的关联关系也会格外清晰。
上面建立了用户-角色-权限表以及其关联表,下面就介绍一些实际的案例吧!
insert into sys_users values(1,'TyCoding','123','salt','管理员',0); insert into sys_roles values(21,'user:create','用户建立',0,0); insert into sys_permissions values(31,'user:create','用户建立',0,0); insert into sys_users_roles values(1,1,21); insert into sys_roles_permissions values(1,21,31);
[mysql> SELECT r.id, r.role, r.description FROM sys_users u, sys_roles r, sys_users_roles ur WHERE u.username = 'TyCoding' AND u.id = ur.user_id AND r.id = ur.role_id; +----+-------+-------------+ | id | role | description | +----+-------+-------------+ | 21 | admin | 管理员 | +----+-------+-------------+ 1 row in set (0.00 sec)
从上面的SQL中足以看出,经过关联表查询另外一张关联的数据要点在于WHERE条件中添加关联表与两张表的关系,在这里便是关联表中存在两张表的主键id,因此把相同的字段加入WHERE条件过滤就能查询到了。
[mysql> SELECT p.id, p.permission, p.description FROM sys_users u, sys_roles r, sys_users_roles ur, sys_permissions p, sys_roles_permissions rp WHERE u.username = 'TyCoding' AND u.id = ur.user_id AND r.id = ur.role_id AND r.id = rp.role_id AND p.id = rp.permission_id; +----+-------------+--------------+ | id | permission | description | +----+-------------+--------------+ | 31 | user:create | 用户建立 | +----+-------------+--------------+ 1 row in set (0.00 sec)
[mysql> SELECT p.id, p.description FROM sys_permissions p, sys_roles r, sys_roles_permissions rp WHERE r.id = 21 AND rp.role_id = r.id AND rp.permission_id = p.id; +----+--------------+ | id | description | +----+--------------+ | 31 | 用户建立 | +----+--------------+ 1 row in set (0.00 sec)
role_id
字段咱们设计的sys_users
表中,存在一个字段role_id
,目的是用来展现当前用户关联的角色名称,可是咱们直接更新sys_roles
表的description
字段时,又不会更新sys_users
表中的role_id
字段。
因此,这里咱们要经过更新的角色数据来更新sys_users
表中的role_id
字段。
[mysql> UPDATE sys_users u, sys_users_roles ur SET u.role_id = '管理员-更新' WHERE ur.role_id = 21 AND u.id = ur.user_id; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> SELECT * FROM sys_users; +----+----------+----------+------+------------------+--------+ | id | username | password | salt | role_id | locked | +----+----------+----------+------+------------------+--------+ | 1 | TyCoding | 123 | salt | 管理员-更新 | 0 | +----+----------+----------+------+------------------+--------+ 1 row in set (0.00 sec)
[mysql> SELECT r.id, r.description, r.pid FROM sys_permissions p, sys_roles r, sys_roles_permissions rp WHERE p.id = 31 AND p.id = rp.permission_id AND r.id = rp.role_id; +----+-------------+------+ | id | description | pid | +----+-------------+------+ | 21 | 管理员 | 0 | +----+-------------+------+ 1 row in set (0.00 sec)
<br/>
若是你们有兴趣,欢迎你们加入个人Java交流群:671017003 ,一块儿交流学习Java技术。博主目前一直在自学JAVA中,技术有限,若是能够,会尽力给你们提供一些帮助,或是一些学习方法,固然群里的大佬都会积极给新手答疑的。因此,别犹豫,快来加入咱们吧!
<br/>
If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.