Shiro 3 shiroFilter

来源:互联网 发布:多益网络 编辑:程序博客网 时间:2024/06/11 04:52

ShiroFilterFactoryBean中getObject()方法

  public Object getObject() throws Exception {        if (instance == null) {            instance = createInstance();        }        return instance;    } protected AbstractShiroFilter createInstance() throws Exception {        log.debug("Creating Shiro Filter instance.");        SecurityManager securityManager = getSecurityManager();        if (securityManager == null) {            String msg = "SecurityManager property must be set.";            throw new BeanInitializationException(msg);        }        if (!(securityManager instanceof WebSecurityManager)) {            String msg = "The security manager does not implement the WebSecurityManager interface.";            throw new BeanInitializationException(msg);        }        FilterChainManager manager = createFilterChainManager();//创建过滤器链管理器        //Expose the constructed FilterChainManager by first wrapping it in a        // FilterChainResolver implementation. The AbstractShiroFilter implementations        // do not know about FilterChainManagers - only resolvers:        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();        chainResolver.setFilterChainManager(manager);        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built        //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class        //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts        //injection of the SecurityManager and FilterChainResolver:        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);    } protected FilterChainManager createFilterChainManager() {        DefaultFilterChainManager manager = new DefaultFilterChainManager();        Map<String, Filter> defaultFilters = manager.getFilters();//1        //apply global settings if necessary:        for (Filter filter : defaultFilters.values()) {            applyGlobalPropertiesIfNecessary(filter);        }        //Apply the acquired and/or configured filters:        Map<String, Filter> filters = getFilters();        if (!CollectionUtils.isEmpty(filters)) {//把配置的filter加入到manager的filteMap中            for (Map.Entry<String, Filter> entry : filters.entrySet()) {                String name = entry.getKey();                Filter filter = entry.getValue();                applyGlobalPropertiesIfNecessary(filter);                if (filter instanceof Nameable) {                    ((Nameable) filter).setName(name);                }                //'init' argument is false, since Spring-configured filters should be initialized                //in Spring (i.e. 'init-method=blah') or implement InitializingBean:                manager.addFilter(name, filter, false);            }        }        //build up the chains:        Map<String, String> chains = getFilterChainDefinitionMap();        if (!CollectionUtils.isEmpty(chains)) {            for (Map.Entry<String, String> entry : chains.entrySet()) {                String url = entry.getKey();                String chainDefinition = entry.getValue();                manager.createChain(url, chainDefinition);//2            }        }        return manager;    } 

//1

DefaultFilterChainManager manager = new DefaultFilterChainManager();

DefaultFilterChainManager中

 public DefaultFilterChainManager() {        this.filters = new LinkedHashMap<String, Filter>();        this.filterChains = new LinkedHashMap<String, NamedFilterList>();        addDefaultFilters(false);    }

 protected void addDefaultFilters(boolean init) {        for (DefaultFilter defaultFilter : DefaultFilter.values()) {            addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);        }    }

public enum DefaultFilter {    anon(AnonymousFilter.class),    authc(FormAuthenticationFilter.class),    authcBasic(BasicHttpAuthenticationFilter.class),    logout(LogoutFilter.class),    noSessionCreation(NoSessionCreationFilter.class),    perms(PermissionsAuthorizationFilter.class),    port(PortFilter.class),    rest(HttpMethodPermissionFilter.class),    roles(RolesAuthorizationFilter.class),    ssl(SslFilter.class),    user(UserFilter.class);

DefaultFilterChainManager为Map<String, Filter> filters添加了默认的过滤器

//2

加入配置的url的过滤器

 public void createChain(String chainName, String chainDefinition) {        if (!StringUtils.hasText(chainName)) {            throw new NullPointerException("chainName cannot be null or empty.");        }        if (!StringUtils.hasText(chainDefinition)) {            throw new NullPointerException("chainDefinition cannot be null or empty.");        }        if (log.isDebugEnabled()) {            log.debug("Creating chain [" + chainName + "] from String definition [" + chainDefinition + "]");        }        //parse the value by tokenizing it to get the resulting filter-specific config entries        //        //e.g. for a value of        //        //     "authc, roles[admin,user], perms[file:edit]"        //        // the resulting token array would equal        //        //     { "authc", "roles[admin,user]", "perms[file:edit]" }        //        String[] filterTokens = splitChainDefinition(chainDefinition);        //each token is specific to each filter.        //strip the name and extract any filter-specific config between brackets [ ]        for (String token : filterTokens) {            String[] nameConfigPair = toNameConfigPair(token);            //now we have the filter name, path and (possibly null) path-specific config.  Let's apply them:            addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);//参数 url,roles,admin,user        }    } public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) {        if (!StringUtils.hasText(chainName)) {            throw new IllegalArgumentException("chainName cannot be null or empty.");        }        Filter filter = 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).");        }        applyChainConfig(chainName, filter, chainSpecificFilterConfig);        NamedFilterList chain = ensureChain(chainName);  //得到以url为key的过滤器列表,加入此过滤器        chain.add(filter);    }    protected void applyChainConfig(String chainName, Filter filter, String chainSpecificFilterConfig) {        if (log.isDebugEnabled()) {            log.debug("Attempting to apply path [" + chainName + "] to filter [" + filter + "] " +                    "with config [" + chainSpecificFilterConfig + "]");        }        if (filter instanceof PathConfigProcessor) {            ((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig);      //注意,设置了指定过滤器的Map<String, Object> appliedPaths key是url value是中括号里面的角色,权限名        } else {            if (StringUtils.hasText(chainSpecificFilterConfig)) {                //they specified a filter configuration, but the Filter doesn't implement PathConfigProcessor                //this is an erroneous config:                String msg = "chainSpecificFilterConfig was specified, but the underlying " +                        "Filter instance is not an 'instanceof' " +                        PathConfigProcessor.class.getName() + ".  This is required if the filter is to accept " +                        "chain-specific configuration.";                throw new ConfigurationException(msg);            }        }    }

接口

public interface PathConfigProcessor {    /**     * Processes the specified {@code config}, unique to the given {@code path}, and returns the Filter that should     * execute for that path/config combination.     *     * @param path   the path for which the {@code config} should be applied     * @param config the configuration for the {@code Filter} specific to the given {@code path}     * @return the {@code Filter} that should execute for the given path/config combination.     */    Filter processPathConfig(String path, String config);}

可以看到Shiro的web过滤器都实现了此接口


整个过程大致就是:

1、配置ShiroFilterFactoryBean的Map<String, Filter> filters 和 Map<String, String> filterChainDefinitionMap 和WebSecurityManager

2、创建SpringShiroFilter过滤器,这个过程需要PathMatchingFilterChainResolver和WebSecurityManager

3、创建 FilterChainManager manager,new出默认的DefaultFilterChainManager(Map<String, Filter> filters,Map<String, NamedFilterList> filterChains) 此过程会给

filters加入默认的过滤器,然后根据ShiroFilterFactoryBean的配置修改部分过滤器中的配置,比如loginurl等,

然后会将ShiroFilterFactoryBean中配置的过滤器filters也配置applyGlobalPropertiesIfNecessary  ,然后加入到 FilterChainManager的filters中,

接着会解析filterChainDefinitionMap中配置的url与权限的信息(xx.action = authc, roles[admin,user], perms[file:edit])

这个过程呢会创建一个NamedFilterList保存符合条件的过滤器 并将这个list放到filterChains中  key为url

而这个符合条件的过滤器就是根据authc或者roles或者其他你配置的过滤器名称,在filters中查找,并且每个过滤器还会去设置类似admin,user的属性,属性名称为

PathMatchingFilter中的Map<String, Object> appliedPaths

4、显然最后的过滤过程就是  SpringShiroFilter得到请求,然后使用FilterChainManager从filterChains中根据url查找过滤器list,创建新的过滤器链,执行过滤器链



0 0
原创粉丝点击