Shiro ShiroFilterFactoryBean的设计概念

web.xml的配置

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <!-- 是否进行下一个过滤链,默认false -->
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

涉及到的Spring部分:DelegatingFilterProxy

我们可以看到起继承了java.servlet.Filter,这里使用到了委派设计模式,实现了Filter,又具备了Filter,filter的实现方法中使用filter去执行,委派设计模式

Filter的行为

init方法对应着initFilterBean方法

@Override
protected void initFilterBean() throws ServletException {
    synchronized (this.delegateMonitor) {
        if (this.delegate == null) {
            // 获得filter-name的值即 shiroFilter
            if (this.targetBeanName == null) {
                this.targetBeanName = getFilterName();
            }
            // 获得SpringContext上下文
            WebApplicationContext wac = findWebApplicationContext();
            if (wac != null) {
                // 初始化下一个Filter
                this.delegate = initDelegate(wac);
            }
        }
    }
}

protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    // 根据beanName(shiroFilter)和Filter(java.servlet.Filter)类型从上下文中获得ShiroFilterBean
    Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
    // 是否初始化下一个Filter过滤器
    if (isTargetFilterLifecycle()) {
        delegate.init(getFilterConfig());
    }
    return delegate;
}

applicationContext-shiro.xml的配置

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="loginUrl" value="/login.do" />
    <property name="successUrl" value="/welcome.do" />
    <!-- 自定义shiro的Filter -->
    <property name="filters">
        <map>
            <entry key="loginFilter" value-ref="loginFilter"></entry>
        </map>
    </property>
    <!--基本系统级别权限配置-->
    <property name="filterChainDefinitions" >
        <value>
            /goods/list.do = loginFilter, user
            /static/** = anno
            /admin/** = anon
        </value>
    </property>
</bean>

<bean id="loginFilter" class="com.wjz.filter.LoginFilter"/>

shiroFilter对应的是ShiroFilterFactoryBean

ShiroFilterFactoryBean

其实现了FactoryBean,当从上下文中获得Bean时会走getObject()方法

public Object getObject() throws Exception {
    if (instance == null) {
        instance = createInstance();
    }
    return instance;
}
    
protected AbstractShiroFilter createInstance() throws Exception {

    log.debug("Creating Shiro Filter instance.");

    // 获得注入进来的SecurityManager
    SecurityManager securityManager = getSecurityManager();
    if (securityManager == null) {
        String msg = "SecurityManager property must be set.";
        throw new BeanInitializationException(msg);
    }

    if (!(securityManager instanceof WebSecurityManager)) {
        String msg = "The security manager does not implement the WebSecurityManager interface.";
        throw new BeanInitializationException(msg);
    }

    // 创建过滤器管理器
    FilterChainManager manager = createFilterChainManager();

    // 创建过滤器解析器
    PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
    // 为过滤器解析器注入过滤器管理器
    chainResolver.setFilterChainManager(manager);

    // 创建一个具体的ShiroFilter实例,将SecurityManager和FilterChainResolver注入进去
    return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}

ShiroFilterFactoryBean$SpringShiroFilter

构造器

protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
    super();
    if (webSecurityManager == null) {
        throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
    }
    // 为ShiroFilter注入SecurityManager
    setSecurityManager(webSecurityManager);
    if (resolver != null) {
        // 为ShiroFilter注入过滤器解析器
        setFilterChainResolver(resolver);
    }
}

Spring调用shiro的Filter的初始化方法:init(FilterConfig filterConfig)方法

public final void init(FilterConfig filterConfig) throws ServletException {
    // 注入FilterConfig和ServletContext
    setFilterConfig(filterConfig);
    try {
        // 执行FilterConfig注入过程中的行为
        onFilterConfigSet();
    } catch (Exception e) {
        if (e instanceof ServletException) {
            throw (ServletException) e;
        } else {
            if (log.isErrorEnabled()) {
                log.error("Unable to start Filter: [" + e.getMessage() + "].", e);
            }
            throw new ServletException(e);
        }
    }
}

AbstractShiroFilter中

protected final void onFilterConfigSet() throws Exception {
    // 校验web.xml中是否配置了staticSecurityManagerEnabled的属性值,有的话则注入
    applyStaticSecurityManagerEnabledConfig();
    // 空方法
    init();
    // 确保SecurityManager已经注入
    ensureSecurityManager();
    // 如果配置的属性值为true则为SecurityUtils注入SecurityManager
    if (isStaticSecurityManagerEnabled()) {
        SecurityUtils.setSecurityManager(getSecurityManager());
    }
}

 

posted @ 2018-07-19 16:33  BINGJJFLY  阅读(2878)  评论(0编辑  收藏  举报