zoukankan      html  css  js  c++  java
  • shiro的DelegatingFilterProxy怎么找到ShiroFilterFactoryBean

    首先看到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类中)
  • 相关阅读:
    phpcms二级菜单
    html5 audio JavaScript 点击播放暂停
    jquery获取type=radio属性的值
    github push 出错:fatal: Authentication failed for 'https://github.com/ ..的解决
    win10远程桌面出现身份验证错误的解决方法
    谷歌和火狐浏览器清除缓存快捷键
    JavaScript的动画
    随机颜色的函数
    JQuery写的一个常见的banner
    网页点击跳转到微信页面
  • 原文地址:https://www.cnblogs.com/qiaozhuangshi/p/10774112.html
Copyright © 2011-2022 走看看