Shiro系列教程ShiroFilter源码分析

来源:互联网 发布:ubuntu 中英字体不同 编辑:程序博客网 时间:2024/06/14 10:11

Shiro系列教程ShiroFilter源码分析


DefaultFilter

//一个枚举类定义了shiro全部的默认拦截器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);    private final Class<? extends Filter> filterClass;    private DefaultFilter(Class<? extends Filter> filterClass) {        this.filterClass = filterClass;    }    public Filter newInstance() {        return (Filter) ClassUtils.newInstance(this.filterClass);    }    public Class<? extends Filter> getFilterClass() {        return this.filterClass;    }    public static Map<String, Filter> createInstanceMap(FilterConfig config) {        Map<String, Filter> filters = new LinkedHashMap<String, Filter>(values().length);        for (DefaultFilter defaultFilter : values()) {            Filter filter = defaultFilter.newInstance();            if (config != null) {                try {                    filter.init(config);                } catch (ServletException e) {                    String msg = "Unable to correctly init default filter instance of type " +                            filter.getClass().getName();                    throw new IllegalStateException(msg, e);                }            }            filters.put(defaultFilter.name(), filter);        }        return filters;    }}


DefaultFilterChainManager

public class DefaultFilterChainManager implements FilterChainManager {    private FilterConfig filterConfig;//存储了所有的shiro filter实例 数据结构如下//roles RolesAuthorizationFilter//ssl SslFilter//全部的包括自定义的    private Map<String, Filter> filters;//存储了路径与对应的filter集合//假设URL定义为=》 /index.jsp=authc, roles[admin,user], perms[file:edit]//则数据结构为  key:/index.jsp    value: list[FormAuthenticationFilter对象,RolesAuthorizationFilter对象,PermissionsAuthorizationFilter对象]    private Map<String, NamedFilterList> filterChains;     public DefaultFilterChainManager() {        this.filters = new LinkedHashMap<String, Filter>();        this.filterChains = new LinkedHashMap<String, NamedFilterList>();//把shiro默认的filter加入到filters        addDefaultFilters(false);    }    public DefaultFilterChainManager(FilterConfig filterConfig) {        this.filters = new LinkedHashMap<String, Filter>();        this.filterChains = new LinkedHashMap<String, NamedFilterList>();//把shiro默认的filter加入到filters        setFilterConfig(filterConfig);        addDefaultFilters(true);    }    public FilterConfig getFilterConfig() {        return filterConfig;    }    public void setFilterConfig(FilterConfig filterConfig) {        this.filterConfig = filterConfig;    }    public Map<String, Filter> getFilters() {        return filters;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setFilters(Map<String, Filter> filters) {        this.filters = filters;    }    public Map<String, NamedFilterList> getFilterChains() {        return filterChains;    }    @SuppressWarnings({"UnusedDeclaration"})    public void setFilterChains(Map<String, NamedFilterList> filterChains) {        this.filterChains = filterChains;    }    public Filter getFilter(String name) {        return this.filters.get(name);    }    public void addFilter(String name, Filter filter) {        addFilter(name, filter, false);    }    public void addFilter(String name, Filter filter, boolean init) {        addFilter(name, filter, init, true);    }//创建filterChain//假设配置的URL为 /index.jsp=authc, roles[admin,user], perms[file:edit]//则chainName=/index.jsp chainDefinition=authc, roles[admin,user], perms[file:edit]    public void createChain(String chainName, String 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]" }        ////传入的为authc, roles[admin,user], perms[file:edit]//返回的数组 ["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) {//传入的是authc 则returned[0] == authc     returned[1] == null//传入的是roles[admin,user] 则returned[0] == roles   returned[1] == admin,user            String[] nameConfigPair = toNameConfigPair(token);//把filter加入到list当中            //例子:传入的是chainName=/index.jsp , nameConfigPair[0]=roles, nameConfigPair[1]=admin,user            addToChain(chainName, nameConfigPair[0], nameConfigPair[1]);        }    }    /**     * Splits the comma-delimited filter chain definition line into individual filter definition tokens.     * <p/>     * Example Input:     * <pre>     *     foo, bar[baz], blah[x, y]     * </pre>     * Resulting Output:     * <pre>     *     output[0] == foo     *     output[1] == bar[baz]     *     output[2] == blah[x, y]     * </pre>     * @param chainDefinition the comma-delimited filter chain definition.     * @return an array of filter definition tokens     * @since 1.2     * @see <a href="https://issues.apache.org/jira/browse/SHIRO-205">SHIRO-205</a>     */    protected String[] splitChainDefinition(String chainDefinition) {        return StringUtils.split(chainDefinition, StringUtils.DEFAULT_DELIMITER_CHAR, '[', ']', true, true);    }    protected String[] toNameConfigPair(String token) throws ConfigurationException {        try {            String[] pair = token.split("\\[", 2);            String name = StringUtils.clean(pair[0]);            if (name == null) {                throw new IllegalArgumentException("Filter name not found for filter chain definition token: " + token);            }            String config = null;            if (pair.length == 2) {                config = StringUtils.clean(pair[1]);                //if there was an open bracket, it assumed there is a closing bracket, so strip it too:                config = config.substring(0, config.length() - 1);                config = StringUtils.clean(config);                //backwards compatibility prior to implementing SHIRO-205:                //prior to SHIRO-205 being implemented, it was common for end-users to quote the config inside brackets                //if that config required commas.  We need to strip those quotes to get to the interior quoted definition                //to ensure any existing quoted definitions still function for end users:                if (config != null && config.startsWith("\"") && config.endsWith("\"")) {                    String stripped = config.substring(1, config.length() - 1);                    stripped = StringUtils.clean(stripped);                    //if the stripped value does not have any internal quotes, we can assume that the entire config was                    //quoted and we can use the stripped value.                    if (stripped != null && stripped.indexOf('"') == -1) {                        config = stripped;                    }                    //else:                    //the remaining config does have internal quotes, so we need to assume that each comma delimited                    //pair might be quoted, in which case we need the leading and trailing quotes that we stripped                    //So we ignore the stripped value.                }            }                        return new String[]{name, config};        } catch (Exception e) {            String msg = "Unable to parse filter chain definition token: " + token;            throw new ConfigurationException(msg, e);        }    }    protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) {        Filter existing = getFilter(name);        if (existing == null || overwrite) {            if (filter instanceof Nameable) {                ((Nameable) filter).setName(name);            }            if (init) {                initFilter(filter);            }            this.filters.put(name, filter);        }    }    public void addToChain(String chainName, String filterName) {        addToChain(chainName, filterName, null);    }    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);//把filter加入到list //数据结构例如:chainName= /index.jsp    filters= roles, authc        NamedFilterList chain = ensureChain(chainName);        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) {//把配置信息设置到filter内部appliedPaths数据结构//chainName = /index.jsp  chainSpecificFilterConfig = admin,user            ((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig);        } else {            if (StringUtils.hasText(chainSpecificFilterConfig)) {                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);            }        }    }    protected NamedFilterList ensureChain(String chainName) {        NamedFilterList chain = getChain(chainName);        if (chain == null) {            chain = new SimpleNamedFilterList(chainName);            this.filterChains.put(chainName, chain);        }        return chain;    }    public NamedFilterList getChain(String chainName) {        return this.filterChains.get(chainName);    }    public boolean hasChains() {        return !CollectionUtils.isEmpty(this.filterChains);    }    public Set<String> getChainNames() {        //noinspection unchecked        return this.filterChains != null ? this.filterChains.keySet() : Collections.EMPTY_SET;    }//创建一个shiro代理的FilterChain    public FilterChain proxy(FilterChain original, String chainName) {        NamedFilterList configured = getChain(chainName);        if (configured == null) {            String msg = "There is no configured chain under the name/key [" + chainName + "].";            throw new IllegalArgumentException(msg);        }        return configured.proxy(original);    }    /**     * Initializes the filter by calling <code>filter.init( {@link #getFilterConfig() getFilterConfig()} );</code>.     *     * @param filter the filter to initialize with the {@code FilterConfig}.     */    protected void initFilter(Filter filter) {        FilterConfig filterConfig = getFilterConfig();        if (filterConfig == null) {            throw new IllegalStateException("FilterConfig attribute has not been set.  This must occur before filter " +                    "initialization can occur.");        }        try {            filter.init(filterConfig);        } catch (ServletException e) {            throw new ConfigurationException(e);        }    }//把shiro默认的filter加入到filters    protected void addDefaultFilters(boolean init) {        for (DefaultFilter defaultFilter : DefaultFilter.values()) {            addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);        }    }}

AbstractShiroFilter

public abstract class AbstractShiroFilter extends OncePerRequestFilter {       protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)            throws ServletException, IOException {        Throwable t = null;        try {            final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);            final ServletResponse response = prepareServletResponse(request, servletResponse, chain);            final Subject subject = createSubject(request, response);            //noinspection unchecked            subject.execute(new Callable() {                public Object call() throws Exception {                    updateSessionLastAccessTime(request, response);                    executeChain(request, response, chain);                    return null;                }            });        } catch (ExecutionException ex) {            t = ex.getCause();        } catch (Throwable throwable) {            t = throwable;        }        if (t != null) {            if (t instanceof ServletException) {                throw (ServletException) t;            }            if (t instanceof IOException) {                throw (IOException) t;            }            //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:            String msg = "Filtered request failed.";            throw new ServletException(msg, t);        }    }    protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {        FilterChain chain = origChain;        FilterChainResolver resolver = getFilterChainResolver();        if (resolver == null) {            log.debug("No FilterChainResolver configured.  Returning original FilterChain.");            return origChain;        }//这里是shiro filter的核心,返回shiro代理的FilterChain//具体可以参考ProxiedFilterChain 先执行shiro的fitler  然后再执行origChain的filter        FilterChain resolved = resolver.getChain(request, response, origChain);        if (resolved != null) {            log.trace("Resolved a configured FilterChain for the current request.");            chain = resolved;        } else {            log.trace("No FilterChain configured for the current request.  Using the default.");        }        return chain;    }}




0 0
原创粉丝点击