Shiro【常用的自定义】

一、前言

在实际开发中,默认的配置往往不满足业务需求,所以就需要进行一些自定义。

二、自定义 Filter

(一)为什么要自定义

在 ShiroConfig 配置类中我们有配置指定角色才能访问的路径,如:

filterChainDefinitionMap.put("/admin/**", "roles[admin]");

但如果我们多加入一个 root 角色的话,如:

filterChainDefinitionMap.put("/admin/**", "roles[admin,root]");

就会要求当前登录的用户必须同时满足这两个角色才能访问。

这其实是不符合需求的,所以我们需要自定义 Filter ,修改其授权的逻辑,实现只需要满足其中任意一个角色就可以访问。

(二)步骤
  1. 编写 Filter 类,继承 AuthorizationFilter 类;

  2. 重写 isAccessAllowed 方法

  3. 在 ShiroConfig 配置类中进行配置

(三)代码实现
  1. 编写 Filter 类,继承 AuthorizationFilter 类 :

  2. 重写 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;
    }
}
  1. 在 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,所以可以自己指定。

(二)步骤
  1. 编写类,实现 SessionIdGenerator 接口

  2. 在 generateId方法中编写生成 sessionId 的代码

  3. 在 SessionDao 中进行设置。由于项目中使用的是 Redis,所以此处需要在 RedisSessionDao 中进行设置

(三)代码实现
  1. 编写类,实现 SessionIdGenerator 接口:

  2. 在 generateId方法中编写生成 sessionId 的代码:

public class CustomSessionIdGenerator implements SessionIdGenerator {
    @Override
    public Serializable generateId(Session session) {
        return "shiro_rbac-"+ UUID.randomUUID().toString().replace("-","");
    }
}
  1. 在 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新手,若有错误,欢迎指正!

posted @ 2021-03-04 15:51  跑调大叔!  阅读(193)  评论(0编辑  收藏  举报