Shiro【常用的自定义】
一、前言
在实际开发中,默认的配置往往不满足业务需求,所以就需要进行一些自定义。
二、自定义 Filter
(一)为什么要自定义
在 ShiroConfig 配置类中我们有配置指定角色才能访问的路径,如:
filterChainDefinitionMap.put("/admin/**", "roles[admin]");
但如果我们多加入一个 root 角色的话,如:
filterChainDefinitionMap.put("/admin/**", "roles[admin,root]");
就会要求当前登录的用户必须同时满足这两个角色才能访问。
这其实是不符合需求的,所以我们需要自定义 Filter ,修改其授权的逻辑,实现只需要满足其中任意一个角色就可以访问。
(二)步骤
编写 Filter 类,继承 AuthorizationFilter 类;
重写 isAccessAllowed 方法
在 ShiroConfig 配置类中进行配置
(三)代码实现
-
编写 Filter 类,继承 AuthorizationFilter 类 :
-
重写 isAccessAllowed 方法:
public class CustomRoleFilter extends AuthorizationFilter {
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
Subject subject = getSubject(request, response);
// 获取 ShiroConfig 配置类中所配置的所有角色
// 如:filterChainDefinitionMap.put("/admin/**", "roles[admin,root]");
String[] rolesArray = (String[]) mappedValue;
//如果没有配置角色限制,可以直接访问
if (rolesArray == null || rolesArray.length == 0) {
return true;
}
Set<String> roles = CollectionUtils.asSet(rolesArray);
//当前 subject 是 roles 中的任意一个,则有权限访问
for(String role : roles){
if(subject.hasRole(role)){
return true;
}
}
return false;
}
}
- 在 ShiroConfig 配置类中进行配置:
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
System.out.println("ShiroFilterFactoryBean加载...");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 1.设置SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
/**
设置一些特殊功能的接口路径
*/
// 其余代码可在项目源码中查看,此处为了篇幅短,故省略
/**
* 设置自定义拦截器
*/
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("customRoleFilter", new CustomRoleFilter());
shiroFilterFactoryBean.setFilters(filterMap);
/**
* 设置拦截路径:对访问路径指定拦截器
*/
// 其余代码可在项目源码中查看,此处为了篇幅短,故省略
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 3.4 角色拦截器(指定角色才可以访问)
// filterChainDefinitionMap.put("/admin/**", "roles[admin,root]");
filterChainDefinitionMap.put("/admin/**", "customRoleFilter[admin,root]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
三、自定义 SessionId
(一)为什么要自定义
在实际开发中,我们可能不想用默认的格式生成 SessionId,所以可以自己指定。
(二)步骤
编写类,实现 SessionIdGenerator 接口
在 generateId方法中编写生成 sessionId 的代码
在 SessionDao 中进行设置。由于项目中使用的是 Redis,所以此处需要在 RedisSessionDao 中进行设置
(三)代码实现
-
编写类,实现 SessionIdGenerator 接口:
-
在 generateId方法中编写生成 sessionId 的代码:
public class CustomSessionIdGenerator implements SessionIdGenerator {
@Override
public Serializable generateId(Session session) {
return "shiro_rbac-"+ UUID.randomUUID().toString().replace("-","");
}
}
- 在 SessionDao 中进行设置:
public RedisSessionDAO redisSessionDAO(){
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(getRedisManager());
//设置 sessionId 生成器
redisSessionDAO.setSessionIdGenerator(new CustomSessionIdGenerator());
return redisSessionDAO;
}
四、ShiroConfig 中常用的 Bean
一些为一些经常在 ShiroConfig 配置类中进行配置的 Bean,了解即可。
/**
* 管理shiro一些bean的生命周期 即:bean初始化与销毁
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 如果要在 controller 中使用 Shiro 的注解,就必须配置这个 Bean 对象
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(getSecurityManager());
return authorizationAttributeSourceAdvisor;
}
/**
* 用来扫描上下文,寻找所有的Advistor(通知器),
* 将符合条件的Advisor应用到切入点的Bean中,需要在LifecycleBeanPostProcessor创建后才可以创建
* @return
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
}
五、项目源代码
链接: https://pan.baidu.com/s/1fKGMSvEmXBItHD6U_pduhg 提取码: jhwy
Java新手,若有错误,欢迎指正!