对shiro的ShiroFilterFactoryBean进行源码解读

1 篇文章 0 订阅
1 篇文章 0 订阅

闲来无事,对这个ShiroFilterFactoryBean,
不理解为什么不直接注入一个Filter,而是一个什么ShiroFilterFactoryBean,于是扒了扒源码,来瞅瞅到底内部是干了什么,
在这里插入图片描述
属于spring包的,那就和spring有关系了,
在这里插入图片描述
是属于shiro-spring的一个兼容包吧,
通过spring得bean注入,
在这里插入图片描述
实际上该类实现了FactoryBean接口,FactoryBean是spring提供的一个接口;
实现该接口可以返回定义的类,

内部属性:
用来放置过滤器的;
Map<String, Filter> filters = new LinkedHashMap();

用来放置url与过滤权限字符串的,例如每个key-value为 “/index”,“anon”
private Map<String, String> filterChainDefinitionMap = new LinkedHashMap();

//主要该类最终还是提供的是这个东东
private AbstractShiroFilter instance;

//剩下的暂时先不管了,不扯那么多,容易理解;
先看看FactoryBean有什么吧;
在这里插入图片描述
其实这个类是一个spring的工厂bean,可以帮助你创建bean,
实现该接口,
设置getObjectType时返回你需要注入的类的class类,
在getObject时返回需要注入的bean即可。
下面的isSingleton意思是是否需要单例。

通过spring的注入方式注入该接口的实现类,即可实现注入指定的类,

ShiroFilterFactoryBean实现了它,
那么看一看它的实现,
在这里插入图片描述
返回了一个内部类SpringShiroFilter,看一看上面的属性,是不是有个AbstractShiroFilter的属性呢?
在这里插入图片描述
实际上AbstractShiroFilter类是SpringShiroFilter的父类,在这里插入图片描述

在这里插入图片描述
实现了FactoryBean的getObject方法,返回了AbstractShiroFilter的实例,
主要看一下this.createInstance()这个方法。
在这里插入图片描述

   protected AbstractShiroFilter createInstance() throws Exception {
        log.debug("Creating Shiro Filter instance.");
        SecurityManager securityManager = this.getSecurityManager();
        String msg;
        //这些都不看,在shiroFactorybean配置的时候我们都会配置这个安全管理器,
        都挺熟的,不说了,
        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 {
        //以上对安全管理器的的问题确认之后,才是正文
        	//这里使用了一个过滤器链管理器,重点是 this.createFilterChainManager()这个方法
            FilterChainManager manager = this.createFilterChainManager();
            PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
            //使用了一个过滤器链解析器,最终返回了作为参数,返回了一个过滤器
            chainResolver.setFilterChainManager(manager);
            return new ShiroFilterFactoryBean.SpringShiroFilter((WebSecurityManager)securityManager, chainResolver);
        }
    }

再看一下createFilterChainManager() 方法

protected FilterChainManager createFilterChainManager() {
//创建了一个链管理器,
        DefaultFilterChainManager manager = new DefaultFilterChainManager();
        //刚创建的就获取filters,怎么还要迭代,里面已经有东西了?等会我们去看下它的构造器,先不管了,肯定里面是有的,
        Map<String, Filter> defaultFilters = manager.getFilters();
        Iterator var3 = defaultFilters.values().iterator();
        //这些迭代的处理this.applyGlobalPropertiesIfNecessary(filter);这个方法没什么看的,无非是放行一些登陆地址,什么成功地址之类的,
        while(var3.hasNext()) {
            Filter filter = (Filter)var3.next();
            this.applyGlobalPropertiesIfNecessary(filter);
        }
		//获取当前类的过滤器
        Map<String, Filter> filters = this.getFilters();
        String name;
        Filter filter;
        if (!CollectionUtils.isEmpty(filters)) {
            for(Iterator var10 = filters.entrySet().iterator(); var10.hasNext(); manager.addFilter(name, filter, false)) {
                Entry<String, Filter> entry = (Entry)var10.next();
                name = (String)entry.getKey();
                filter = (Filter)entry.getValue();
                this.applyGlobalPropertiesIfNecessary(filter);
                if (filter instanceof Nameable) {
                    ((Nameable)filter).setName(name);
                }
            }
        }
	//这里的filterChainDefinitionMap其实就是我们放入的验证规则,

        Map<String, String> chains = this.getFilterChainDefinitionMap();
        if (!CollectionUtils.isEmpty(chains)) {
            Iterator var12 = chains.entrySet().iterator();

            while(var12.hasNext()) {
                Entry<String, String> entry = (Entry)var12.next();
                String url = (String)entry.getKey();
                String chainDefinition = (String)entry.getValue();
                //通过管理器进行创建链,主要看这个方法,后面会介绍
                manager.createChain(url, chainDefinition);
            }
        }

        return manager;
    }

然后看下这个过滤器链管理器吧
构造器:
在这里插入图片描述
看到构造器调用了addDefaualtFilter方法,咱看下吧;
在这里插入图片描述

protected void addDefaultFilters(boolean init) {
	//这个是什么鬼?
	//其实是个枚举类啦!
	就是添加了一堆过滤器
        DefaultFilter[] var2 = DefaultFilter.values();
        int var3 = var2.length;
        for(int var4 = 0; var4 < var3; ++var4) {
            DefaultFilter defaultFilter = var2[var4];
            //defaultFilter.newInstance(),创建实例
            this.addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false);
      }
 }

下面是这个枚举类的源码:

public enum DefaultFilter {
//声明了一堆我们shiro自带的过滤器,名称(对应的过滤器类)
    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);

    private final Class<? extends Filter> filterClass;

    private DefaultFilter(Class<? extends Filter> filterClass) {
        this.filterClass = filterClass;
    }
	//调用这个方法创建了一个实例
    public Filter newInstance() {
        return (Filter)ClassUtils.newInstance(this.filterClass);
    }

    public Class<? extends Filter> getFilterClass() {
        return this.filterClass;
    }
......
}

再看下上面说的 manager.createChain(url, chainDefinition);这个方法;
这个就是根据你的url进行配置对应的过滤器了,
在这里插入图片描述
大致就扯到这里吧,反正东扯西扯,也不一定讲的很明白。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
web.xml配置 因为我们是与spring进行集成的,而spring的基本就是web项目的xml文件。所以我们在web.xml中配置shiros的过滤拦截。正常情况下,我们需要将shirofilter配置在所有的filter前面,当然和encodingFilter这个filter是不区分前后的。因为两者互相不影响的。spring-shiro.xml 这里我们将来看看spring-shiro.xml的配置,这里我采取倒叙的方式讲解,我觉的倒叙更加的有助于我们理解代码。首先我们还记得在web.xml中配置的那个filter吧,名字shiroFilter,对spring-shiro.xml配置文件就是通过这个filter展开的。首先我们在web.xml配置的过滤器实际上是配置ShiroFilterFactoryBean,所以在这里需要将ShiroFilterFactoryBean定义为shiroFilter <!-- Shiro的核心安全接口,这个属性是必须的 --> <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.html"页面 --> <!-- 登录成功后要跳转的连接 --> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp --> <!-- Shiro连接约束配置,即过滤链的定义 --> <!-- 此处可配合我的这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 --> <!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 --> <!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 --> <!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter --> /statics/**=anon /login.html=anon /sys/schedule.html=perms[sys:schedule:save] /sys/login=anon /captcha.jpg=anon /**=authc

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值