目录
Shiro五张表
在Web应用中,对安全的控制主要有角色、资源、权限(什么角色能访问什么资源)几个概念,一个用户可以有多个角色,一个角色也可以访问多个资源,也就是角色可以对应多个权限
数据库设计,至少需要建5张表:用户表、用户-角色表、角色表、角色-资源表、资源表
①一个用户对应一个或者多个角色。
②一个角色对应一个或者多个权限。
③一个权限对应能够访问对应的API或URL资源。
(1)用户表
用户表中至少包含以上的字段,主键id、用户名username、密码password、盐值salt(因为密码是经过Shiro加密的,需要通过盐值校验,由Shiro生成,不需要用户手动填写)、角色列表roleId(这个字段不是必须的,仅实现在展示用户信息的时候能同时展示用户当前角色)、是否锁定locked(决定当前账户是否是锁定的)。
创建新的用户,仅需要输入用户名和密码即可,盐值由Shiro生成,角色列表和是否锁定都可以在后期管理。
其中locked是否锁定字段类型为tinyint(1),设置这种类型,数据库中实际存储的是int类型数据,一般是0和1,在使用Mybatis取这个字段的数据时,Mybatis会自动将tinyint(1)字段值为0的转换成false,将字段值为1以上的转换为true
(2)用户-角色表
用户-角色表比较简单,仅仅包含了用户ID:user_id、角色ID:role_id,使用了联合主键
这张表主要描述指定用户与角色间的依赖关系。其中用户表与角色表是一对多的关系,一个用户可以拥有多个角色
(3)角色表
角色表中role角色名称一般为存储着类似user:create这种格式,Shiro在Realm中校验用户身份的时候会通过role这个字段值进行校验;remark是此角色的描述信息,比如:用户创建
其中parentId表示父节点,就是说,当前的角色可能有上级节点,如果存在父节点,这个字段值就是父级节点的ID,根据这个ID,在展示数据的时候就很方便的展示出其在哪个父节点下
parentId:用于超级管理员,对角色及其权限的控制。
如果存在子节点,则显示为目录。不存在子节点,则显示问文件图标。形成树状结构。
locked表示当前节点是否锁定,同样是tinyint(1)类型,如果为false就说明没有锁定
(4)角色-权限(菜单)表
角色-资源(权限)表和用户-角色表类似。包含了角色ID:role_id、权限ID(菜单):menu_id(permission_id)
主要描述角色和权限间的依赖关系,同样,角色和权限间也是一对多的关系,一个角色会关联多个权限
(5)权限(菜单)表
权限(资源)表中menu权限名称一般为存储着类似admin/**(URL)格式,Shiro在Realm中授权的时候会通过path这个字段值进行授权
locked表示当前节点是否锁定,同样是tinyint(1)类型,如果为false就说明没有锁定
为什么不设计外键?
比如:用户表和角色表间,这里创建了用户-角色表来实现两者的关联;并没有通过给两张表建立外键来实现一对多、多对多的关联关系
如果要建立外键来关联两张表,会遇到如下问题:
(1)如果两张表之间存在一对多的关系,在给一的一方新增数据的时候,要考虑多的一方是否存在指定的id
(2)如果两张表之间存在一对多的关系,在删除多的一方时你要先删除其关联的一的一方,再删除多的一方
也就是说如果使用了外键关联,那么在对表进行数据操作时就必须考虑另一张关联的表,相当于两张表就绑在一起了,操作这张表就必须考虑另一张关联表
但是实际开发中,不想立即就修改或更新关联表的数据,可能一会再去更新另一张关联表的数据,那么就产生了这种方式:通过单独建立一张关联来实现两张表的数据关联
所以,建议在设计表时尽量减少表与表直接的外键约束,这样能避免很多麻烦,并且两张表之间的关联关系也会格外清晰