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
- Shiro系列教程ShiroFilter源码分析
- shiro源码分析之shiroFilter初始化过程
- Shiro源码学习之ShiroFilter
- Shiro系列教程 AccessControlFilter源码分析
- Shiro系列教程拦截器Filter源码分析
- Shiro 3 shiroFilter
- shiro 系列教程
- Shiro源码分析
- Shiro 之 Filter(上):ShiroFilter
- ShiroFilter
- Shiro源码分析-初始化-Realm
- shiro认证授权源码分析
- Shiro源码分析-初始化-SecurityManager
- shiro注解授权源码分析
- Shiro源码分析----认证流程
- Shiro源码分析----登录流程
- Shiro源码分析----授权流程
- Shiro源码分析----认证流程
- HEVC代码学习8:xMotionEstimation函数
- 选择排序,冒泡排序,归并排序,快速排序,堆排序等等
- PHP统计在线用户数
- Python学习笔记
- 如何在本地打开远程服务端口
- Shiro系列教程ShiroFilter源码分析
- spring容器启动事件和关闭事件
- NWBC连接配置及使用
- LIUNX inode 空间饱和,耗尽 的 排查,解决方法
- 计算机专业要不要考研——写的很棒
- Auth2.0 java方式实现代码
- cornerstone创建分支与合并代码方法整理
- redis 基础篇
- Centos7安装Redis-3.2.5集群