zoukankan      html  css  js  c++  java
  • 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());
        }
    }
  • 相关阅读:
    转:[windows]DOS批处理添加任务计划
    转:winform_webApiSelfHost及 OWIN WebAPI Service
    Ubuntu上将终端安装到右键上
    Ubuntu上安装VMware tools
    OpenStack中的rabbitmq的配置方法
    centos上的grub文件修改
    centos7上安装0penStack
    怎样使用yum安装OpenStack
    epel扩展库的安装
    centos7上修改主机名
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/9336636.html
Copyright © 2011-2022 走看看