当前位置: 首页 > article >正文

Shiro权限刷新

一、权限刷新的需求背景

在实际应用中,用户的权限可能会因为多种原因而发生变化,如用户角色的调整、权限的授予或撤销等。如果系统不能及时地反映这些变化,就可能导致安全漏洞或功能受限。因此,Shiro框架提供了权限刷新的机制,以确保系统的安全性和功能的完整性。

二、权限刷新的实现方式

  1. 通过重新加载权限配置

    • Shiro允许开发者在权限配置发生变化时,重新加载权限配置。这通常涉及到修改权限配置文件或数据库中的权限信息,并调用Shiro框架提供的API来重新加载这些配置。
    • 例如,在Shiro的Spring Boot集成中,可以通过调用ShiroFilterFactoryBeansetFilterChainDefinitionMap方法来重新设置权限过滤链。
  2. 通过清除缓存

    • Shiro在认证和授权过程中会使用缓存来提高性能。然而,当用户权限发生变化时,这些缓存信息可能会变得过时。
    • 因此,Shiro提供了清除缓存的机制。开发者可以在修改用户权限后,调用Shiro的API来清除相关的认证和授权缓存,从而确保权限刷新的有效性。
    • 例如,在自定义的Realm中,可以通过调用getAuthenticationCache().removegetAuthorizationCache().remove方法来清除特定用户的认证和授权缓存。
  3. 通过动态构建权限过滤器

    • Shiro支持动态构建权限过滤器,这意味着开发者可以在运行时根据用户的权限信息来构建过滤器链。
    • 当用户权限发生变化时,可以重新构建过滤器链以反映这些变化。
    • 这通常涉及到获取当前的权限信息、构建新的过滤器链,并将其应用到Shiro的过滤器管理器中。

三、权限刷新的注意事项

  1. 同步性

    • 在多用户并发访问的场景下,需要确保权限刷新的同步性,以避免因权限信息不一致而导致的安全问题。
  2. 性能

    • 频繁的权限刷新可能会对系统性能产生影响。因此,需要在确保安全性的前提下,合理地控制权限刷新的频率。
  3. 异常处理

    • 在权限刷新过程中,可能会遇到各种异常情况,如数据库连接失败、配置文件解析错误等。因此,需要做好异常处理,确保系统的稳定性和可用性。

MyShiroRealm

// 清空 当前认证用户权限缓存
    public void clearMyCachedAuthorizationInfo(){
        clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

    // 清空所有用户权限缓存
    public void clearAllCacheAuthorizationInfo(){
        if (this.isAuthorizationCachingEnabled()){// 权限缓存是否可用
            Cache<Object, AuthorizationInfo> cache = null;
            CacheManager cacheManager = this.getCacheManager();
            if (cacheManager != null){
                String cacheName = this.getAuthorizationCacheName();// 获得权限缓存
                cache = cacheManager.getCache(cacheName);// 获得权限缓存
            }
            if (cache != null){
                cache.clear();// 清空
            }
        }
    }

权限刷新方法

public Map loadFilterChainDefinitions() {

        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();// 必须使用LinkedHashMap(有序集合)
        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/fonts/**","anon");
        filterChainDefinitionMap.put("/images/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/localcss/**","anon");
        filterChainDefinitionMap.put("/localjs/**","anon");

        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/logout","logout");// 注销过滤器,自动注销

        // 配置需要特点权限才能访问的资源(URL)
        // 动态授权

        List<SRight> rights = roleMapper.findAllRights();
        for (SRight right : rights) {
            if (right.getRightUrl() != null && !right.getRightUrl().trim().equals("")){
                filterChainDefinitionMap.put(right.getRightUrl(),"perms[" + right.getRightCode() + "]");
                System.out.println("动态授权:" + right.getRightText());
            }
        }


        // 配置认证访问:其他资源(URL)必须认证通过才能访问
        filterChainDefinitionMap.put("/**","authc");// 必须放在过滤器链的最后面

        return filterChainDefinitionMap;
    }

    public void reloadFilterChainDefinitions() {
        try {
            HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
            ServletContext servletContext = request.getSession().getServletContext();
            AbstractShiroFilter shiroFilter = (AbstractShiroFilter) WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).getBean("shiroFilterFactory");
            synchronized (shiroFilter){
                // 获取过滤管理器
                PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
                DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
                // 清空初始权限权限
                manager.getFilterChains().clear();
                // 重新加载动态权限,配置权限验证规则
                Map<String, String> chains = loadFilterChainDefinitions();
                // System.out.println("chains--------" + chains);
                for (Map.Entry<String, String> entry : chains.entrySet()) {
                    String url = entry.getKey();
                    String chainDefinition =  entry.getValue().trim().replace("","");
                    manager.createChain(url, chainDefinition);
                }
                System.out.println("更新权限成功!!");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }


http://www.kler.cn/a/386539.html

相关文章:

  • luckfox-pico-max学习记录
  • 高性能分布式缓存Redis-高可用部署
  • Matlab实现鹈鹕优化算法(POA)求解路径规划问题
  • 《重学Java设计模式》之 原型模式
  • 万字长文解读深度学习——卷积神经网络CNN
  • AndroidStudio-文本显示
  • 「C/C++」C/C++标准库 之 #include<cstdlib> 通用工具函数库
  • hive表批量造数据
  • 08、Java学习-面向对象中级:
  • MySQL约束管理
  • 微服务day04
  • 技术速递|.NET 9 中 System.Text.Json 的新增功能
  • Linux命令 - linux索引节点、硬链接、软链接的介绍与使用
  • 一个简单ASP.NET购物车设计
  • 从0开始linux(24)——文件(5)磁盘文件系统
  • SpringBoot3中swagger无法使用
  • C#-密封类、密封方法
  • acmessl.cn提供接口API方式申请免费ssl证书
  • 第 2 章 - Go语言环境搭建
  • C++builder中的人工智能(16):神经网络中的SoftPlus激活函数
  • 网络安全应急响应(归纳)
  • AscendC从入门到精通系列(一)初步感知AscendC
  • 「Mac玩转仓颉内测版3」入门篇3 - Cangjie的基本语法与结构
  • rediss数据结构及其底层实现
  • C++代码优化(三): 决不要重新定义继承而来的缺省参数值
  • Android中桌面小部件的开发流程及常见问题和解决方案