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()); } }