一、权限刷新的需求背景

在实际应用中,用户的权限可能会因为多种原因而发生变化,如用户角色的调整、权限的授予或撤销等。如果系统不能及时地反映这些变化,就可能导致安全漏洞或功能受限。因此,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();
        }
    }

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部