shiro过滤器原理解析

DelegatingFilterProxy

DelegatingFilterProxy的作用:传统方式通过web.xml注入filter,该filter就交给web容器来管理了,但是该filter也就不能注入spring容器的某些bean。DelegatingFilterProxy就是为了解决这类问题,虽然DelegatingFilterProxy实现了Filter接口,但是内部没有任何关于过滤方面的逻辑,它只是spring容器里某个实现了Filter接口的过滤器Bean的代理,实际使用的是它所代理的那个过滤器的过滤逻辑(ps:DelegatingFilterProxy与spring容器的过滤器bean是通过beanName建立联系的)。因此,spring的DelegatingFilterProxy提供了在 web.xml和application context之间的联系。另外需要注意的是,虽然DelegatingFilterProxy内部没有过滤器相关逻辑,但是它本质还是一个过滤器,使用任然需要在web.xml里面配置,而filter-name的值就是它所代理filter的bean的name。

过滤器配置

DelegatingFilterProxy这个作用带来的意义是,如果我们使用的不是shiro过滤器,而是其他的安全框架,那么,只需要在spring容器中配置相应的filter,交由DelegatingFilterProxy代理即可,降低了代码的耦合性。

ShiroFilterFactoryBean之AbstractShiroFilter

image.png

AbstractShiroFilter是shiro的全局过滤器,所有的请求都会经过该过滤器,在该过滤器内部,每次访问都会调用session.touch()方法更新会话最后访问时间。但是使用的时候,并没有注入AbstractShiroFilter,那么AbstractShiroFilter是如何配置和使用的呢?

使用过shiro都知道,过滤器是通过ShiroFilterFactoryBean进行注入的,但是其并不是一个过滤器,只是有个AbstractShiroFilter过滤器属性。

个人理解在springboot中,springboot完成了DelegatingFilterProxy的相关配置(ps:如果不使用springboot,那么这一步需要自己手动配置,配置方式看上面的DelegatingFilterProxy过滤器配置),然后DelegatingFilterProxy从spring容器中获取AbstractShiroFilter类型的bean进行了代理。

DelegatingFilterProxy从spring容器中获取AbstractShiroFilter类型的bean进行代理,但是我们在使用的过程中并没有将AbstractShiroFilter交由spring容器管理,只将ShiroFilterFactoryBean添加到了spring容器中,它是如何获取的呢,这里就要谈谈FactoryBean这个接口了。

FactoryBean主要方法

package org.springframework.beans.factory;

import org.springframework.lang.Nullable;

public interface FactoryBean {
    //获取实例
    T getObject() throws Exception;
    //获取提供实例的类型
    Class getObjectType();
    //是否单例,个人认为如果不是单例将会把实例放到spring容器里
    default boolean isSingleton() {
        return true;
    }

}

在spring通过类型获取AbstractShiroFilter类型bean的时候(ps:注意,在spring容器里没有AbstractShiroFilter类型的bean),会将所有beanName获取出来,然后遍历beanName集合,根据beanName获取bean并判断该bean是否实现了FactoryBean,如果实现了FactoryBean就调用该bean实现的FactoryBean的getObjectType获取类型,判断需要的类型与该类型是否匹配,如果匹配,通过其实现的getObject()获取创建一个实例作为bean。而看ShiroFilterFactoryBean源码,由于其实现了FactoryBean接口,在spring上下文获取其的时候,会调用getObject方法获取,实际获取的是其属性AbstractShiroFilter的过滤器。而AbstractShiroFilter内部维护着定义好的过滤器链。

ShiroFilterFactoryBean的getObject源码

public Object getObject() throws Exception {
        if (this.instance == null) {
            this.instance = this.createInstance();
        }

        return this.instance;
    }
    protected AbstractShiroFilter createInstance() throws Exception {
        log.debug("Creating Shiro Filter instance.");
        SecurityManager securityManager = this.getSecurityManager();
        String msg;
        if (securityManager == null) {
            msg = "SecurityManager property must be set.";
            throw new BeanInitializationException(msg);
        } else if (!(securityManager instanceof WebSecurityManager)) {
            msg = "The security manager does not implement the WebSecurityManager interface.";
            throw new BeanInitializationException(msg);
        } else {
            FilterChainManager manager = this.createFilterChainManager();
            PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
            chainResolver.setFilterChainManager(manager);
            return new ShiroFilterFactoryBean.SpringShiroFilter((WebSecurityManager)securityManager, chainResolver);
        }
    }

实际返回的是其内部类AbstractShiroFilter。该类就是shiro核心的过滤器。

你可能感兴趣的:(shiro过滤器原理解析)