了解Acegi第一步

Acegi认证详解

      最近在研究spring的认证框架acegi,记录一下自己的理解。
      Acegi是基于Spring的一个开源的安全认证框架,现在的最新版本是1.0.7。Acegi的特点就是有很多的过滤器,具体项目中能用到哪些过滤器,则进行配置即可。
      Acegi资源包下载: http://mirrors.ibiblio.org/pub/mirrors/maven2/org/acegisecurity/acegi-security/
      Acegi的官网: http://www.acegisecurity.org/
      Acegi是以过滤器的方式来使用的,在WEB程序中,就得在web.xml中配置过滤器,如果在web.xml配置许多的过滤器,肯定会出现配置文件过大和初始化及Filter的管理得问题,Acegi提供了用spring容器来管理Filter的配置方式:
Web.xml文件中:

<filter>
		<filter-name>Acegi-Filter</filter-name>
		<filter-class>
			org.acegisecurity.util.FilterToBeanProxy
		</filter-class>
		<init-param>
			<param-name>targetClass</param-name>
			<param-value>
				org.acegisecurity.util.FilterChainProxy
			</param-value>
		</init-param>
</filter>

 applicationContext-acegi-security.xml文件中:

<bean id="filterChainProxy"
		class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
		CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
/j_acegi_security_check*=httpSessionContextIntegrationFilter,authenticationProcessingFilter
/**/*=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>
		</property>
	</bean>

      让我们来看看发生了什么:
      在FilterToBeanProxy类中还可以配置的参数有targetBean,它代表spring容器中Bean对象,而targetClass这代表Bean容器中配置的Filter。配置他们可以达到同样的效果,就是从spring容器中的到相应的Bean对象,也就是FilterChainProxy对象。当请求被Acegi-Filter过滤器截获后,FilterToBeanProxy将请求交给FilterChainProxy对象处理。当FilterChainProxy接受请求时,它首先根据filterInvocationDefinitionSource的配置来得到本次请求所要经过的过滤器列表。FilterInvocationDefinitionSource有多个实现类。其中用的较多的是PathBaseFilterInvocationDefinitionMap类。他将配置的每一个Key-Value对封装成一个EntryHolder对象,然后保存在requestMap的list中。PathBaseFilterInvocationDefinitionMap会首先得到请求的url,然后根据这个url在requestMap找到符合条件的EntryHolder对象,然后得到ConfigAttributeDefinition对象,其中保存的是配置的Filter列表:PathBaseFilterInvocationDefinitionMap:lookAttributes(String url)

Iterator iter = requestMap.iterator();
        while (iter.hasNext()) {
            EntryHolder entryHolder = (EntryHolder) iter.next();
//判断请求的url与配置的path是否相符
            boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);
            if (logger.isDebugEnabled()) {
                logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getAntPath() + "; matched="
                        + matched);
            }
            if (matched) {//如果找到,这返回EntryHolder中的ConfigAttributeDefinition对象,其中保存有对应的Filter列表
                return entryHolder.getConfigAttributeDefinition();
            }
        }

 得到了ConfigAttributeDefinition对象,然后得到其中的所有的Filter:
PathBaseFilterInvocationDefinitionMap:obtainAllDefinedFilter(ConfigAttributeDefinition configAttributeDefinition)

Iterator attributes = configAttributeDefinition.getConfigAttributes();
        while (attributes.hasNext()) {
            ConfigAttribute attr = (ConfigAttribute) attributes.next();
            String filterName = attr.getAttribute();
            if (filterName == null) {
                throw new IllegalArgumentException("Configuration attribute: '" + attr
                    + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy");
            }
            if (!filterName.equals(TOKEN_NONE)) {
                list.add(this.applicationContext.getBean(filterName, Filter.class));
            }
        }

        return (Filter[]) list.toArray(new Filter[list.size()]);

      其中我们看到如果filterName.equals(TOKEN_NONE),则这个Filter不加入到处理的Filter对列中,所以如果要想某个请求不经过这些过滤器,则可以配成:path=#NONE#
然后FilterChainProxy将所有的过滤器保存在一个VirtualFilterChain对象中,将所有过滤器的调用交给VirtualFilterChain对象:VirtualFilterChain:

public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
            if (currentPosition == additionalFilters.length) {
                if (logger.isDebugEnabled()) {
                    logger.debug(fi.getRequestUrl()
                        + " reached end of additional filter chain; proceeding with original chain");
                }
                fi.getChain().doFilter(request, response);
            } else {
                currentPosition++;
                if (logger.isDebugEnabled()) {
                    logger.debug(fi.getRequestUrl() + " at position " + currentPosition + " of "
                        + additionalFilters.length + " in additional filter chain; firing Filter: '"
                        + additionalFilters[currentPosition - 1] + "'");
                }
                additionalFilters[currentPosition - 1].doFilter(request, response, this);
            }
        }

 这样VirtualFilterChain将按filterChainProxy中配置的Filter顺序来一个个执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值