Shiro源码----加载

之前的项目的授权框架用的是spring-sercet,其实Shiro和它类似,都是用于用户认证,授权。所以看Shiro的源码理解起来不是很费劲,如果你之前没有阅读过有关权限框架的,或者没有接触过的话,可以先去了解下内部过程。

此篇主要分析下Shiro的加载过程。

老规矩,从web.xml入手,因为这种类似的权限框架大多是通过Filter来实行过滤的。 

1. web.xml

	<!-- Shiro Filter -->  
    <filter>  
        <filter-name>shiroFilter</filter-name>  
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
        <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>

简单明了,DelegatingFilterProxy只是一个代理,它为bean的获取提供了便利,其实很多人一开始不熟悉,以为这边就是Shrio的入口。其实不是,此处配置说明最终执行流程交给了shiroFilter。

2. spring-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="filterChainDefinitions">
        <value>
            /login.do = anon
            /dologin.do = anon
            /** = authc <!--需要认证 -->
        </value>
    </property>
</bean>

可以看见ShiroFilterFactoryBean才是shiro配置里的核心类,shiroFilter这个bean就是通过它生成出来的。这个bean当前配置了几个属性。

securityManager:安全管理器

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <!--安全管理器-->
    <property name="sessionManager" ref="sessionManager" />
    <!-- 自定义数据访问连接器-->
    <property name="realm" ref="shiroRealm" />
    <!-- 自定义缓存设置-->
    <property name="cacheManager" ref="cacheManager" />
</bean>

<!-- 设置超时时间,cookie名称等-->
<bean id="sessionManager"
      class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <!-- session 设置,一般可以继承redis存放session-->
    <property name="sessionDAO" ref="sessionDAO" />
    <property name="sessionIdCookie" ref="cookie"/>
    <property name="sessionIdCookieEnabled" value="true"/>
</bean>

filterChainDefinitions:过滤器配置,配置一些请求的访问限制策略。

3.ShiroFilterFactoryBean

3.1 setFilterChainDefinitions

因为配置文件里有属性的注入,所以我们先去看下filterChainDefinitions的set操作。主要就是存储XML内配置的拦截策略。

public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor {

    private Map<String, String> filterChainDefinitionMap;

    public void setFilterChainDefinitions(String definitions) {
        Ini ini = new Ini();
        ini.load(definitions);
        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
        if (CollectionUtils.isEmpty(section)) {
            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        setFilterChainDefinitionMap(section);
    }

    /**
     *  /login.do = anon
     *  /dologin.do = anon
     *  /** = authc
     *  保存为map格式的数据就可以知道哪些请求应用哪些拦截策略,比如anno,authc
     *
      */
    public void setFilterChainDefinitionMap(Map<String, String> filterChainDefinitionMap) {
        this.filterChainDefinitionMap = filterChainDefinitionMap;
    }
}

3.1 getObject

 另外我们看见这个类继承自FactoryBean,因此它肯定是同过getObject获取到shiroFilter这个对象,因此我们直接看这个方法。

public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor {

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

主要方法就是createInstance,此方法内主要分成3个步骤分别组装核心数据securityManager,FilterChainManager,PathMatchingFilterChainResolver。

1.SecurityManager securityManager = getSecurityManager();

2.FilterChainManager manager = createFilterChainManager();

3.PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();

protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance.");
        // 1. 获取安全配置器
        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);
        }

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

        // 3. 创建基于路径匹配的过滤器链解析器
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);

        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }

createFilterChainManager();

protected FilterChainManager createFilterChainManager() {

        //获取默认过滤器链管理器
        DefaultFilterChainManager manager = new DefaultFilterChainManager();
        Map<String, Filter> defaultFilters = manager.getFilters();
        //配置一些全局的配置参数,主要设置loginUrl,successUrl等
        for (Filter filter : defaultFilters.values()) {
            applyGlobalPropertiesIfNecessary(filter);
        }

        //获取配置文件内配置的个性化Filter,不过此例中没有配置
        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();
                applyGlobalPropertiesIfNecessary(filter);
                if (filter instanceof Nameable) {
                    ((Nameable) filter).setName(name);
                }
                manager.addFilter(name, filter, false);
            }
        }

        //构造过滤器链
        Map<String, String> chains = getFilterChainDefinitionMap();
        if (!CollectionUtils.isEmpty(chains)) {
            for (Map.Entry<String, String> entry : chains.entrySet()) {
                //此处获取到配置文件内配置的过滤策略,设置到FilterChainManager内,
                // 这样就知道哪些url配置了哪些规则以及对应的Filter
                // url = login.do  chainDefinition = anon --> AnonymousFilter
                // url = dologin.do  chainDefinition = anon --> AnonymousFilter
                // url = /**  chainDefinition = authc --> FormAuthenticationFilter
                String url = entry.getKey();
                String chainDefinition = entry.getValue();
                manager.createChain(url, chainDefinition);
            }
        }

        return manager;
    }

我们看第一步创建DefaultFilterChainManager()时做了哪些操作,可以看见给了shiro内配置的默认值和默认配置对应的Filter。

    //默认过滤器链构造器,值取自DefaultFilter默认值中,
    //可以看见,我们配置的anon,authc等都有自己的Filter
    public DefaultFilterChainManager() {
        this.filters = new LinkedHashMap<String, Filter>();
        this.filterChains = new LinkedHashMap<String, NamedFilterList>();
        addDefaultFilters(false);
    }
    protected void addDefaultFilters(boolean init) {
        for (DefaultFilter defaultFilter : DefaultFilter.values()) {
            addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
        }
    }
    public enum DefaultFilter {
        anon(AnonymousFilter.class),
        authc(FormAuthenticationFilter.class),
        authcBasic(BasicHttpAuthenticationFilter.class),
        logout(LogoutFilter.class),
        noSessionCreation(NoSessionCreationFilter.class),
        perms(PermissionsAuthorizationFilter.class),
        port(PortFilter.class),
        rest(HttpMethodPermissionFilter.class),
        roles(RolesAuthorizationFilter.class),
        ssl(SslFilter.class),
        user(UserFilter.class);
    }

最终构造出的mapper过滤器链如下图:filterChains内对应了配置的3种拦截方式和过滤方式以及对应的Filter类

 

最后pathMatchingFilterChainResolver这个解析器的设置也很简单,直接将上面获取到filterChains设置进去就行。

4. SpringShiroFilter

最后构造出一个SpringShiroFilter 返回出去,这样项目启动时SpringShiroFilter对象构建就完成了,接下来就是请求过程中的认证和授权步骤了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值