shiro框架源码解析与改造(三)---FilterChainManager

在ShiroFilterFactoryBean中,在创建filter实例时,调用了createFilterChainManager()方法来创建FilterChainManager,并对FilterChainManager 的一些变量进行了初始化 。

 /**
     * 把拦截链,以及过滤器放进manager
     * @return
     */
    private FilterChainManager createFilterChainManager() {
        DefaultFilterChainManager manager=new DefaultFilterChainManager();
        Map<String, Filter> filters = this.getFilters();
        String name;
        Filter filter;
        if(!CollectionUtils.isEmpty(filters)) {
            for(Iterator var10 = filters.entrySet().iterator(); var10.hasNext(); manager.addFilter(name, filter, false)) {
                Map.Entry<String, Filter> entry = (Map.Entry)var10.next();
                name = (String)entry.getKey();
                filter = (Filter)entry.getValue();
                if(filter instanceof Nameable) {
                    ((Nameable)filter).setName(name);
                }
            }
        }
        Map<String, String> chains = this.getFilterChainDefinitionMap();
        if(!CollectionUtils.isEmpty(chains)) {
            Iterator var12 = chains.entrySet().iterator();

            while(var12.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry)var12.next();
                String url = (String)entry.getKey();
                String chainDefinition = (String)entry.getValue();
                manager.createChain(url, chainDefinition);
            }
        }

        return manager;

    }

首先是第一行调用构造函数创建对象,在构造函数中,添加了默认的过滤器。

        public DefaultFilterChainManager() {
            this.addDefaultFilters(false);
        }

默认的构造器有很多个,都在DefaultFilters这个类中,DefaultFilters是一个枚举类。其中比较重要的是authc,perm这2个,它们分别是认证和授权的过滤器。

protected void addDefaultFilters(boolean init) {
        DefaultFilters[] var2 = DefaultFilters.values();
        int var3 = var2.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            DefaultFilters defaultFilter = var2[var4];
            this.addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
        }
    }

看完了构造方法,再回到createFilterChainManager()中,下面这一行是获取开发人员自定义的filter,然后把它们添加到DefaultFilterChainManager中。

Map<String, Filter> filters = this.getFilters();

再然后,把开发人员自定义的权限拦截链添加到 DefaultFilterChainManager中。

 Map<String, String> chains = this.getFilterChainDefinitionMap();
 if(!CollectionUtils.isEmpty(chains)) {
            Iterator var12 = chains.entrySet().iterator();

            while(var12.hasNext()) {
                Map.Entry<String, String> entry = (Map.Entry)var12.next();
                String url = (String)entry.getKey();
                String chainDefinition = (String)entry.getValue();
                manager.createChain(url, chainDefinition);
            }
        }

关于getFilterChainDefinitionMap()方法,它是构建拦截链的核心方法,开发人员如果想自定义拦截链的数据源(比如说从数据库中加载权限配置),则需要重写这个方法。

public Map<String, String> getFilterChainDefinitionMap() {
        if (CollectionUtils.isEmpty(this.filterChainDefinitionMap)){
            this.setFilterChainDefinitions();
        }
        return this.filterChainDefinitionMap;
    }
public void setFilterChainDefinitions() {
        try {
            Map<String,String> perms= this.readConfigPerms();
            this.setFilterChainDefinitionMap(perms);
        } catch (IOException |URISyntaxException e) {
            if (log.isDebugEnabled()){
                log.debug(fileName+"读取出错:"+e);
            }
        }
        if (urlChains!=null){
            Map<String,String> permsChain= urlChains.buildChainMap();
            this.setFilterChainDefinitionMap(permsChain);
        }
    }

我这里从2个地方读取拦截链信息,一个是配置文件中perm.properties,另外一个是
数据库中。
这一行是从数据库中读取并添加到拦截链中

Map<String,String> permsChain= urlChains.buildChainMap();

urlChains是一个接口,定义了一个方法。

public interface UrlChains {
    Map<String,String> buildChainMap();
}

我这里是从redis缓存中读取权限,然后加载到shiro中。

public Map<String, String> buildChainMap() {
        Map<String, String> permsMap = new HashMap<>();
            List<String> perms = cacheManager.hvals(CommonField.Operate_Perms);
            for (String perm : perms) {
                permsMap.put(perm, "perms[\"" + perm + "\"]");
            }
        return permsMap;
    }

接下来是FilterChainManager的一个重要方法createChain(url, chainDefinition);前面大部分都是ShiroFilterFactoryBean中的代码。

  @Override
    public void createChain(String chainName, String chainDefinition) {
        if(!StringUtils.hasText(chainName)) {
            throw new NullPointerException("chainName cannot be null or empty.");
        } else if(!StringUtils.hasText(chainDefinition)) {
            throw new NullPointerException("chainDefinition cannot be null or empty.");
        } else {
            if(LOG.isDebugEnabled()) {
                LOG.debug("Creating chain [" + chainName + "] from String definition [" + chainDefinition + "]");
            }

            String[] filterTokens = this.splitChainDefinition(chainDefinition);
            int length = filterTokens.length;

            for(int i = 0; i < length; ++i) {
                String token = filterTokens[i];
                String[] nameConfigPair = this.toNameConfigPair(token);
                this.addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);
            }

        }
    }

addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);

 /**
     * 给filterChains添加一个对象,key是url,v是它将经过的拦截链
     * @param chainName  目标Url
     * @param filterName perm,auth等类型
     * @param chainSpecificFilterConfig 需要的权限等。
     */
    @Override
    public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig){
        if (!StringUtils.hasText(chainName)){
            throw new IllegalArgumentException("chainName cannot be null or empty.");
        }else {
            Filter filter=this.getFilter(filterName);
            if(filter == null) {
                throw new IllegalArgumentException("There is no filter with name '" + filterName + "' to apply to chain [" + chainName + "] in the pool of available Filters.  Ensure a filter with that name/path has first been registered with the addFilter method(s).");
            } else {
                this.applyChainConfig(chainName, filter, chainSpecificFilterConfig);
                NamedFilterList chain = this.ensureChain(chainName);
                chain.add(filter);
            }
        }
    }

FilterChainManager有三个成员变量。filters 存放所有的过滤器,filterChains 存放每一个拦截链需要执行的过滤器。

  private FilterConfig filterConfig;
    private Map<String, Filter> filters = new LinkedHashMap();
    private Map<String, NamedFilterList> filterChains = new LinkedHashMap();

FilterChainManager另一个重要方法proxy

 @Override
    public FilterChain proxy(FilterChain original, Collection<String> chainNames) {
        NamedFilterList namedFilterList=null;
        if (chainNames!=null && chainNames.size()>0){
            Iterator<String> stringIterator=chainNames.iterator();
            while (stringIterator.hasNext()){
                String chainName=stringIterator.next();
                if (namedFilterList==null){
                    namedFilterList=this.getChain(chainName);
                }else {
                    namedFilterList.addAll(this.getChain(chainName));
                }
            }
        }
//        NamedFilterList namedFilterList=this.getChain(chainName);
        if(namedFilterList == null) {
            String msg = "There is no configured chain under the name/key [" + chainNames + "].";
            throw new IllegalArgumentException(msg);
        } else {
            return namedFilterList.proxy(original);
        }
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值