shiro的DelegatingFilterProxy怎么找到ShiroFilt…
2019-04-26 08:21:39来源:博客园 阅读 ()
首先看到web.xml中的配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!-- 这里配置你的ShiroFilterFactoryBean的spring配置文件 -->
</param-value>
</context-param>
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <async-supported>true</async-supported> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
现在就引出一个问题,这里配置了ShiroFilterFactoryBean 和 DelegatingFilterProxy对象,显然这两个只是一个工厂Bean和一个委托代理对象 那么真正的shiro入口过滤器在哪儿 ?
我们进入DelegatingFilterProxy
发现其构造方法是空的
public DelegatingFilterProxy() { }
但是它的父类GenericFilterBean实现了InitializingBean, 那么就多了个afterPropertiesSet方法
GenericFilterBean
@Override public void afterPropertiesSet() throws ServletException { initFilterBean(); }
DelegatingFilterProxy
@Override protected void initFilterBean() throws ServletException { synchronized (this.delegateMonitor) { if (this.delegate == null) { // 这个是DelegatingFilterProxy配置的名字 shiroFilter if (this.targetBeanName == null) { this.targetBeanName = getFilterName(); } WebApplicationContext wac = findWebApplicationContext(); if (wac != null) { //初始化 this.delegate = initDelegate(wac); } } } }
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
//从spring上下文中根据shiroFilter(DelegatingFilterProxy配置的名字) 获取bean
Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
AbstractApplicationContext
@Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name, requiredType); }
AbstractBeanFactory
@Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); }
//最终走到了doGetBean
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 根据web里面配置的shiroFilter的名字在spring容器中获取到了ShiroFilterFactoryBean Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 通过工厂获取对象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }return (T) bean; }
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//其中有这么一句,从工厂Bean中获取Bean实例
if (object == null) {
...
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
FactoryBeanRegistrySupport 经过枯燥的源码调用 ,来到了大门口
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName) throws BeanCreationException { Object object; try { else { //调用ShiroFilterFactoryBean的getObjectct方法, ShiroFilterFactoryBean实现了FactoryBean object = factory.getObject(); } } return object; }
现在让我们来看看ShiroFilterFactoryBean
public Object getObject() throws Exception { if (instance == null) { instance = createInstance(); } return instance; }
protected AbstractShiroFilter createInstance() throws Exception { SecurityManager securityManager = getSecurityManager();
//这里有个创建过滤连管理器的方法 我们也要看看 FilterChainManager manager = createFilterChainManager(); PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); chainResolver.setFilterChainManager(manager); //这里就是最终的那个shiro的入口Filter 是 AbstractShiroFilter的子类 return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver); }
那么SpringShiroFilter就长这样,这个就是shiro的入口Filter,每次调用都会先调用它(doFilter方法在父类AbstractShiroFilter 中)
private static final class SpringShiroFilter extends AbstractShiroFilter { protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) { super(); if (webSecurityManager == null) { throw new IllegalArgumentException("WebSecurityManager property cannot be null."); } setSecurityManager(webSecurityManager); if (resolver != null) { setFilterChainResolver(resolver); } } }
然后我们再看看createFilterChainManager
protected FilterChainManager createFilterChainManager() {
//其中包含了11个默认的过滤器 DefaultFilterChainManager manager = new DefaultFilterChainManager();
//默认的11个过滤器 Map<String, Filter> defaultFilters = manager.getFilters(); // 添加登陆、登陆成功、没有认证 的url(如果设置了的话) for (Filter filter : defaultFilters.values()) { applyGlobalPropertiesIfNecessary(filter); } /在xml文件的<property name="filters">中配置的过滤 Map<String, Filter> filters = getFilters(); if (!CollectionUtils.isEmpty(filters)) { for (Map.Entry<String, Filter> entry : filters.entrySet()) {
//拦截规则 String name = entry.getKey();
//过滤器 Filter filter = entry.getValue();
// 添加登陆、登陆成功、没有认证 的url(如果设置了的话) applyGlobalPropertiesIfNecessary(filter);
//设置名字 if (filter instanceof Nameable) { ((Nameable) filter).setName(name); }
//添加自定义的过滤器, 因为spring容器启动时初始化过自定义的过滤器,所以这个为初始化参数为false manager.addFilter(name, filter, false); } } //<property name="filterChainDefinitions">中设置的规则与过滤器 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); } } return manager;
}
// 给 “每一个” 满足类型的过滤器添加添加登陆、登陆成功、没有认证 的url(如果设置了的话) private void applyGlobalPropertiesIfNecessary(Filter filter) { // 需要是AccessControlFilter类型 applyLoginUrlIfNecessary(filter); // 需要是 AuthenticationFilter类型 applySuccessUrlIfNecessary(filter); //需要是AuthorizationFilter 类型 applyUnauthorizedUrlIfNecessary(filter); }
DefaultFilterChainManager
//创建过滤链 public void createChain(String chainName, String chainDefinition) { // 过滤器可以写成这样 { "authc", "roles[admin,user]", "perms[file:edit]" } String[] filterTokens = splitChainDefinition(chainDefinition); //这里让每一个PathConfigProcessor类型的过滤器都有该过滤器对应的所有规则 这里遍历的是过滤链字符串 for (String token : filterTokens) { String[] nameConfigPair = toNameConfigPair(token); //添加过滤器到过滤链(一个规则对应一条过滤链) addToChain(chainName, nameConfigPair[0], nameConfigPair[1]); } } //添加过滤器到过滤链 public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) { //根据名称获取过滤器 Filter filter = getFilter(filterName); //配置过滤链 applyChainConfig(chainName, filter, chainSpecificFilterConfig); NamedFilterList chain = ensureChain(chainName); chain.add(filter); } //配置过滤链 protected void applyChainConfig(String chainName, Filter filter, String chainSpecificFilterConfig) { //如果当前过滤器是PathConfigProcessor类型 处理之 if (filter instanceof PathConfigProcessor) { ((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig); } }
PathMatchingFilter 这里将同一过滤器的所有规则设置给当前过滤器 比如 /aa=anon /bb=anon 如果当前请求的路径是/aa 它对应的过滤器是anon 这里的appliedPaths就会有 /aa 和 /bb两个元素
简单理解为当前拦截路径所对应的过滤器类型 对应的拦截路径(--!)
public Filter processPathConfig(String path, String config) { String[] values = null; if (config != null) { values = split(config); } // 添加过滤链的名称 this.appliedPaths.put(path, values); return this; }
小结:
1、在启动后生成 shiroFilter -- SpringShiroFilter 入口过滤器(ShiroFilterFactoryBean类中)
2、在会以拦截规则为key,后面的过滤器生成一条过滤链为 value的形式生成存放在map中(DefaultFilterChainManager类中)
3、会给每个AccessControlFilter类型过滤器设置 登陆、登陆成功、没有认证 的url(ShiroFilterFactoryBean类中)
吐槽一下这个随便的编辑器,
1、代码插入在最后就不能回车写在外面了,比如我这都嵌在代码块里面
2、写的时候会卡死,只能写中文还不能选中等等
原文链接:https://www.cnblogs.com/qiaozhuangshi/p/10774112.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 作为一个面试官,我想问问你Redis分布式锁怎么搞? 2020-06-10
- 怎么用Java 高效提取、替换、删除PDF文档中的图片 2020-06-09
- dockerMesos配置项是怎么解析的?案例详解 2020-06-02
- JVM 怎么判断对象已经死了? 2020-06-01
- 引入mybatis-plus报 Invalid bound statement错误怎么办,动 2020-05-28
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash