首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

Shiro框架Web环境下过滤器构造分析

2012-07-01 
Shiro框架Web环境下过滤器结构分析http://blog.csdn.net/jacky_zuo/article/details/7000402Shiro的过滤器

Shiro框架Web环境下过滤器结构分析
http://blog.csdn.net/jacky_zuo/article/details/7000402



Shiro的过滤器的配置是结合使用Spring的DelegatingFilterProxy与FactoryBean2种技术来完成自身过滤器的植入的,所以理解Shiro的过滤器首先要理解这2者的使用。



1. DelegatingFilterProxy

Spring提供的一个简便的过滤器的处理方案,它将具体的操作交给内部的Filter对象delegate去处理,而这个delegate对象通过Spring IOC容器获取,这里采用的是Spring的FactoryBean的方式获取这个对象。

DelegatingFilterProxy的配置如下
[html] view plaincopyprint?
<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,但是它并做任何实际的工作,而是把工作交由Spring中容器为bean的名字shiroFilter的类,即ShiroFilterFactoryBean;

2. ShiroFilterFactoryBean

配置如下

[html] view plaincopyprint?
<bean id="shiroFilter" + continueChain + "]"); 
            } 
 
            if (continueChain) { 
                executeChain(request, response, chain); 
            } 
 
            postHandle(request, response); 
            if (log.isTraceEnabled()) { 
                log.trace("Successfully invoked postHandle method"); 
            } 
 
        } catch (Exception e) { 
            exception = e; 
        } finally { 
            cleanup(request, response, exception); 
        } 
    } 
从上面的代码可以看出,其核心的逻辑是3个部分: preHandle, executeChain,postHandle。后2者都只有该类中有唯一的实现,子类并不覆盖,而preHandle则由一个子类PathMatchingFilter中覆盖,代码如下:
[java] view plaincopyprint?
public boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { 
 
        if (this.appliedPaths == null || this.appliedPaths.isEmpty()) { 
            if (log.isTraceEnabled()) { 
                log.trace("appliedPaths property is null or empty.  This Filter will passthrough immediately."); 
            } 
            return true; 
        } 
 
        for (String path : this.appliedPaths.keySet()) { 
            // If the path does match, then pass on to the subclass implementation for specific checks 
            //(first match 'wins'): 
            if (pathsMatch(path, request)) { 
                if (log.isTraceEnabled()) { 
                    log.trace("Current requestURI matches pattern [" + path + "].  Performing onPreHandle check..."); 
                } 
                Object config = this.appliedPaths.get(path); 
                return onPreHandle(request, response, config); 
            } 
        } 
 
        //no path matched, allow the request to go through: 
        return true; 
    } 
这个方法根据用户请求的地址是否与该Filter配置的地址匹配来决定是否调用内部的onPreHandler方法。从shiroFilter中的属性filterChainDefinitions配置中可以看出,shiro默认的那些过滤器如user,roles,perms等等都可以统一使用这种方式,对于内部的处理则分别由各个Filter的onPreHandler(其实是由内部的isAccessAllowed和onAccessDenied方法)来决定了。

举2个例子

第一个是AuthenticationFilter的isAccessAllowed方法,它只检测用户是否通过验证

[java] view plaincopyprint?
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { 
        Subject subject = getSubject(request, response); 
        return subject.isAuthenticated(); 
    } 
第二个是RolesAuthorizationFilter的isAccessAllowed方法,它检测用户的角色是否满足
[java] view plaincopyprint?
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { 
 
       Subject subject = getSubject(request, response); 
       String[] rolesArray = (String[]) mappedValue; 
 
       if (rolesArray == null || rolesArray.length == 0) { 
           //no roles specified, so nothing to check - allow access. 
           return true; 
       } 
 
       Set<String> roles = CollectionUtils.asSet(rolesArray); 
       return subject.hasAllRoles(roles); 
   } 

热点排行
Bad Request.