文章目录
序:
本文使用springboot
+mybatis
+SpringSecurity
实现数据库动态的管理用户、角色、权限管理
本文细分角色和权限,并将用户、角色、权限和资源均采用数据库存储,并且自定义滤器,代替原有的FilterSecurityInterceptor
过滤器,
并分别实现AccessDecisionManager
、InvocationSecurityMetadataSourceService
和UserDetailsService
,并在配置文件中进行相应配置。
源码地址:
源码地址:https://gitee.com/zenghua3300/SpringSecurity
喜欢的小伙伴麻烦帮点一个star
spring security的简单原理:
使用众多的拦截器对url
拦截,以此来管理权限。但是这么多拦截器,笔者不可能对其一一来讲,主要讲里面核心流程的两个。
首先,权限管理离不开登陆验证的,所以登陆验证拦截器AuthenticationProcessingFilter
要讲;
还有就是对访问的资源管理吧,所以资源管理拦截器AbstractSecurityInterceptor
要讲;
但拦截器里面的实现需要一些组件来实现,所以就有了AuthenticationManager
、accessDecisionManager
等组件来支撑。
现在先大概过一遍整个流程,用户登陆,会被AuthenticationProcessingFilter
拦截,调用AuthenticationManager
的实现,而且AuthenticationManager
会调用ProviderManager
来获取用户验证信息(不同的Provider
调用的服务不同,因为这些信息可以是在数据库上,可以是在LDAP
服务器上,可以是xml
配置文件上等),如果验证通过后会将用户的权限信息封装一个User
放到spring
的全局缓存SecurityContextHolder
中,以备后面访问资源时使用。
访问资源(即授权管理),访问url
时,会通过AbstractSecurityInterceptor
拦截器拦截,其中会调用FilterInvocationSecurityMetadataSource
的方法来获取被拦截url所需的全部权限,在调用授权管理器AccessDecisionManager
,这个授权管理器会通过spring
的全局缓存SecurityContextHolder
获取用户的权限信息,还会获取被拦截的url
和被拦截url
所需的全部权限,然后根据所配的策略(有:一票决定,一票否定,少数服从多数等),如果权限足够,则返回,权限不够则报错并调用权限不足页面。
security认证过程:
security授权过程:
重要
本文设计和代码是基于 上一篇博客(请点击)
进行修改。
目录结构如下:
1:数据库表设计
由于本文增加了权限表所以本文的数据库表为5个分别是: 用户表
、角色表
、权限表
、用户角色中间表
、角色权限中间表
初始化数据
注意:Sys_permission 表的url通配符为两颗星,比如说 /user下的所有url,应该写成 /user/**;
权限的名字可以随意起名
CREATE TABLE `sys_permission_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_id` int(11) DEFAULT NULL, `permission_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
CREATE TABLE `sys_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `descritpion` varchar(255) DEFAULT NULL, `url` varchar(255) DEFAULT NULL, `pid` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
insert into sys_user (id,username, password) values (1,'admin', 'admin'); insert into sys_user (id,username, password) values (2,'abel', 'abel'); insert into sys_role(id,name) values(1,'ROLE_ADMIN'); insert into sys_role(id,name) values(2,'ROLE_USER'); insert into sys_role_user(Sys_User_id,Sys_Role_id) values(1,1); insert into sys_role_user(Sys_User_id,Sys_Role_id) values(2,2); BEGIN; INSERT INTO `Sys_permission` VALUES ('1', 'ROLE_HOME', 'home', '/', null), ('2', 'ROLE_ADMIN', 'ABel', '/admin', null); COMMIT; BEGIN; INSERT INTO `Sys_permission_role` VALUES ('1', '1', '1'), ('2', '1', '2'), ('3', '2', '1'); COMMIT;
insert into SYS_USER (id,username, password) values (1,'admin', 'admin');
insert into SYS_USER (id,username, password) values (2,'abel', 'abel');
insert into SYS_ROLE(id,name) values(1,'ROLE_ADMIN');
insert into SYS_ROLE(id,name) values(2,'ROLE_USER');
INSERT INTO SYS_ROLE_USER(SYS_USER_ID,SYS_ROLE_ID) VALUES(1,1);
INSERT INTO SYS_ROLE_USER(SYS_USER_ID,SYS_ROLE_ID) VALUES(2,2);
BEGIN;
INSERT INTO `Sys_permission` VALUES ('1', 'ROLE_HOME', 'home', '/', null), ('2', 'ROLE_ADMIN', 'ABel', '/admin', null);
COMMIT;
BEGIN;
INSERT INTO `Sys_permission_role` VALUES ('1', '1', '1'), ('2', '1', '2'), ('3', '2', '1');
COMMIT;
2:权限表的业务代码
2.1 java bean
Permission.java
package com.us.example.domain;
/**
* Created by yangyibo on 17/1/20.
*/
public class Permission {
private int id;
//权限名称
private String name;
//权限描述
private String descritpion;
//授权链接
private String url;
//父节点id
private int pid;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescritpion()