shiro自定义Realm
三、SpringBoot整合Shiro完成权限管理案例—自定义Realm
使用JdbcRealm可以完成用户权限管理,但是我们必须提供JdbcRealm规定的数据表结构;如果在我们的项目开发中 ,这个JdbcRealm规定的数据表结构不能满足开发需求,该如何处理呢?
- 自定义数据库表结构
- 自定义Realm实现认证和授权
3.1 数据库设计
RBAC基于角色的访问控制
-- 用户信息表
create table tb_users(
user_id int primary key auto_increment,
username varchar(60) not null unique,
password varchar(20) not null,
password_salt varchar(60)
);
insert into tb_users(username,password) values('zhangsan','123456');
insert into tb_users(username,password) values('lisi','123456');
insert into tb_users(username,password) values('wangwu','123456');
insert into tb_users(username,password) values('zhaoliu','123456');
insert into tb_users(username,password) values('chenqi','123456');
-- 角色信息表
create table tb_roles(
role_id int primary key auto_increment,
role_name varchar(60) not null
);
insert into tb_roles(role_name) values('admin');
insert into tb_roles(role_name) values('cmanager'); -- 仓管
insert into tb_roles(role_name) values('xmanager'); -- 销售
insert into tb_roles(role_name) values('kmanager'); -- 客服
insert into tb_roles(role_name) values('zmanager'); -- 行政
-- 权限信息表
create table tb_permissions(
permission_id int primary key auto_increment, -- 1
permission_code varchar(60) not null, -- sys
find
permission_name varchar(60) -- 仓库查询
);
insert into tb_permissions(permission_code,permission_name) values('sys
save','入库');
insert into tb_permissions(permission_code,permission_name) values('sys
delete','出库');
insert into tb_permissions(permission_code,permission_name) values('sys
update','修改');
insert into tb_permissions(permission_code,permission_name) values('sys
find','查询');
insert into tb_permissions(permission_code,permission_name) values('sys
save','新增订单');
insert into tb_permissions(permission_code,permission_name) values('sys
delete','删除订单');
insert into tb_permissions(permission_code,permission_name) values('sys
update','修改订单');
insert into tb_permissions(permission_code,permission_name) values('sys
find','查询订单');
insert into tb_permissions(permission_code,permission_name) values('sys
save','新增客户');
insert into tb_permissions(permission_code,permission_name) values('sys
delete','删除客户');
insert into tb_permissions(permission_code,permission_name) values('sys
update','修改客户');
insert into tb_permissions(permission_code,permission_name) values('sys
find','查询客户');
-- 用户角色表
create table tb_urs(
uid int not null,
rid int not null
-- primary key(uid,rid),
-- constraint FK_user foreign key(uid) references tb_users(user_id),
-- constraint FK_role foreign key(rid) references tb_roles(role_id)
);
insert into tb_urs(uid,rid) values(1,1);
insert into tb_urs(uid,rid) values(1,2);
insert into tb_urs(uid,rid) values(1,3);
insert into tb_urs(uid,rid) values(1,4);
insert into tb_urs(uid,rid) values(1,5);
insert into tb_urs(uid,rid) values(2,2);
insert into tb_urs(uid,rid) values(3,3);
insert into tb_urs(uid,rid) values(4,4);
insert into tb_urs(uid,rid) values(5,5);
-- 角色权限表
create table tb_rps(
rid int not null,
pid int not null
);
-- 给仓管角色分配权限
insert into tb_rps(rid,pid) values(2,1);
insert into tb_rps(rid,pid) values(2,2);
insert into tb_rps(rid,pid) values(2,3);
insert into tb_rps(rid,pid) values(2,4);
-- 给销售角色分配权限
insert into tb_rps(rid,pid) values(3,4);
insert into tb_rps(rid,pid) values(3,5);
insert into tb_rps(rid,pid) values(3,6);
insert into tb_rps(rid,pid) values(3,7);
insert into tb_rps(rid,pid) values(3,8);
insert into tb_rps(rid,pid) values(3,9);
insert into tb_rps(rid,pid) values(3,10);
insert into tb_rps(rid,pid) values(3,11);
insert into tb_rps(rid,pid) values(3,12);
-- 给客服角色分配权限
insert into tb_rps(rid,pid) values(4,11);
insert into tb_rps(rid,pid) values(4,12);
-- 给行政角色分配权限
insert into tb_rps(rid,pid) values(5,4);
insert into tb_rps(rid,pid) values(5,8);
insert into tb_rps(rid,pid) values(5,12);
3.2 DAO实现
Shiro进行认证需要用户信息:
- 根据用户名查询用户信息
Shiro进行授权管理需要当前用户的角色和权限
- 根据用户名查询当前用户的角色列表(3张表连接查询)
- 根据用户名查询当前用户的权限列表(5张表连接查询)
3.2.1 创建SpringBoot项目,整合MyBatis
3.2.2 根据用户名查询用户信息
创建BeanBean
@Data
public class User {private Integer userId;
private String userName;
private String userPwd;
private String pwdSalt;
}
创建DAO
public interface UserDAO {
public User queryUserByUsername(String username) throws Exception;
}
映射配置
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3.2.3 根据用户名查询角色名列表
创建DAO
public interface RoleDAO {
public Set<String> queryRoleNamesByUsername(String username) throws Exception;
}
映射配置
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3.2.4 根据用户名查询权限列表
创建DAO
public interface PermissionDAO {
public Set<String> queryPermissionsByUsername(String username) throws Exception;
}
映射配置
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3.3 整合Shiro
导入依赖
org.apache.shiro
shiro-spring
1.4.1
com.github.theborakompanioni
thymeleaf-extras-shiro
2.0.0 配置Shiro-基于Java配置方式
@Configuration
public class ShiroConfig {
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
//自定义Realm
@Bean
public MyRealm getMyRealm(){
MyRealm myRealm = new MyRealm();
return myRealm;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//过滤器就是shiro就行权限校验的核心,进行认证和授权是需要SecurityManager的
filter.setSecurityManager(securityManager);
Map<String,String> filterMap = new HashMap<>();
filterMap.put("/","anon");
filterMap.put("/index.html","anon");
filterMap.put("/login.html","anon");
filterMap.put("/regist.html","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/layui/**","anon");
filterMap.put("/**","authc");
filter.setFilterChainDefinitionMap(filterMap);
filter.setLoginUrl("/login.html");
//设置未授权访问的页面路径()
filter.setUnauthorizedUrl("/login.html");
return filter;
}
}
自定义Realm
/**
- 1.创建一个类继承AuthorizingRealm类(实现了Realm接口的类)
- 2.重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
3.重写getName方法返回当前realm的一个自定义名称
*/
public class MyRealm extends AuthorizingRealm {@Resource
private UserDAO userDAO;
@Resource
private RoleDAO roleDAO;
@Resource
private PermissionDAO permissionDAO;
public String getName() {return "myRealm";
}
/**
- 获取授权数据(将当前用户的角色及权限信息查询出来)
/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取用户的用户名
String username = (String) principalCollection.iterator().next();
//根据用户名查询当前用户的角色列表
SetroleNames = roleDAO.queryRoleNamesByUsername(username);
//根据用户名查询当前用户的权限列表
Setps = permissionDAO.queryPermissionsByUsername(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roleNames);
info.setStringPermissions(ps);
return info;
}
/* - 获取认证的安全数据(从数据库查询的用户的正确数据)
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//参数authenticationToken就是传递的 subject.login(token)
// 从token中获取用户名
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
//根据用户名,从数据库查询当前用户的安全数据
User user = userDAO.queryUserByUsername(username);
AuthenticationInfo info = new SimpleAuthenticationInfo(
username, //当前用户用户名,对应doGetAuthorizationInfo中的PrincipalCollection
user.getUserPwd(), //从数据库查询出来的安全密码
getName());
return info;
}
}
还没有评论,来说两句吧...