ShiroFilterFactoryBean源码及拦截原理深入分析

本篇文章篇幅比较长,但是细看下去相信对学习Shiro应该会有帮助。好了,闲话不多说,直接进入正题:

Shiro提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前端控制器,其是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。

而要在Spring中使用Shiro的话,可在web.xml中配置一个DelegatingFilterProxy,DelegatingFilterProxy作用是自动到Spring容器查找名字为shiroFilter(filter-name)的bean并把所有Filter的操作委托给它。

首先是在web.xml中配置DelegatingFilterProxy

<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后,下面只要再把ShiroFilter配置到Spring容器(此处为Spring的配置文件)即可:

<bean id=”shiroFilter” class=”org.apache.shiro.spring.web.ShiroFilterFactoryBean”><=”securityManager”/></bean>

可以看到我们使用了ShiroFilterFactoryBean来创建shiroFilter,这里用到了Spring中一种特殊的Bean——FactoryBean。当需要得到名为”shiroFilter“的bean时,会调用其getObject()来获取实例。下面我们通过分析ShiroFilterFactoryBean创建实例的过程来探究Shiro是如何实现安全拦截的:

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

其中调用了createInstance()来创建实例:

protected AbstractShiroFilter createInstance() throws Exception {// 这里是通过FactoryBean注入的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);return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);}

可以看到创建SpringShiroFilter时用到了两个组件:SecurityManager和ChainResolver。

先有一个大体的了解,那么对于源码分析会有不少帮助。下面会对以上两个重要的组件进行分析,包括PathMatchingFilterChainResolver和FilterChainManager。首先贴一段ShiroFilter的在配置文件中的定义:

========>=”filterChainDefinitions”><value>/resources/** = anon/plugin/** = anon/download/** = anon/special/unauthorized = anon/register = anon/login = ssl,authc/logout = logout/admin/** = roles[admin]/** = user>

再来看看PathMatchingFilterChainResolver和FilterChainManager的创建过程:

protected FilterChainManager createFilterChainManager() {// 默认使用的FilterChainManager是DefaultFilterChainManagerDefaultFilterChainManager manager = new DefaultFilterChainManager();, Filter> defaultFilters = manager.getFilters();// 将ShiroFilterFactoryBean配置的一些公共属性(上面配置的loginUrl,successUrl,unauthorizeUrl)应用到默认注册的filter上去for (Filter filter : defaultFilters.values()) {applyGlobalPropertiesIfNecessary(filter);}, Filter> filters = getFilters();if (!CollectionUtils.isEmpty(filters)) {for (, Filter> entry : filters.entrySet()) {String name = entry.getKey();Filter filter = entry.getValue();applyGlobalPropertiesIfNecessary(filter);if (filter instanceof Nameable) {((Nameable) filter).setName(name);}// 将Filter添加到manager中去,可以看到对于Filter的管理是依赖于FilterChainManager的manager.addFilter(name, filter, false);}}, String> chains = getFilterChainDefinitionMap();if (!CollectionUtils.isEmpty(chains)) {for (, String> entry : chains.entrySet()) {String url = entry.getKey();String chainDefinition = entry.getValue();// 后面会分析该步的源码,功能上就是创建Filter链manager.createChain(url, chainDefinition);}}return manager;}待人对事不要太计较,如果太计较就会有悔恨!

ShiroFilterFactoryBean源码及拦截原理深入分析

相关文章:

你感兴趣的文章:

标签云: