Acegi 的配|看h非常复杂,但事实上在实际项目的安全应用中我们ƈ不需要那么多功能,清楚的了解Acegi配置中各的功能Q有助于我们灉|的运用Acegi于实践中?/p>
2.1 在Web.xml中的配置
1) FilterToBeanProxy
Acegi通过实现了Filter接口的FilterToBeanProxy提供一U特D的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy来完成过滤功能,q好处是化了web.xml的配|,q且充分利用了Spring IOC的优ѝFilterChainProxy包含了处理认证过E的filter列表Q每个filter都有各自的功能?/p>
<filter>
<filter-name>Acegi Filter Chain Proxy</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>
2) filter-mapping
<filter-mapping>限定了FilterToBeanProxy的URL匚w模式,只有*.do?.jsp?j_acegi_security_check 的请求才会受到权限控Ӟ对javascript,css{不限制?/p>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/j_acegi_security_check</url-pattern>
</filter-mapping>
3) HttpSessionEventPublisher
<listener>的HttpSessionEventPublisher用于发布HttpSessionApplicationEvents和HttpSessionDestroyedEvent事glspring的applicationcontext?/p>
<listener>
<listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
FilterChainProxy会按序来调用这些filter,使这些filter能n用Spring ioc的功? CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义了url比较前先转ؓ写Q?PATTERN_TYPE_APACHE_ANT定义了用Apache ant的匹配模?
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,
basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,
exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
1) authenticationManager
起到认证理的作用,它将验证的功能委托给多个ProviderQƈ通过遍历Providers, 以保证获取不同来源的w䆾认证Q若某个Provider能成功确认当前用Lw䆾Qauthenticate()Ҏ会返回一个完整的包含用户授权信息的Authentication对象Q否则会抛出一个AuthenticationException?br />Acegi提供了不同的AuthenticationProvider的实?如:
DaoAuthenticationProvider 从数据库中读取用户信息验证n?br /> AnonymousAuthenticationProvider 匿名用户w䆾认证
RememberMeAuthenticationProvider 已存cookie中的用户信息w䆾认证
AuthByAdapterProvider 使用容器的适配器验证n?br /> CasAuthenticationProvider ҎYale中心认证服务验证w䆾, 用于实现单点登陆
JaasAuthenticationProvider 从JASS登陆配置中获取用户信息验证n?br /> RemoteAuthenticationProvider Ҏq程服务验证用户w䆾
RunAsImplAuthenticationProvider 对n份已被管理器替换的用戯行验?br /> X509AuthenticationProvider 从X509认证中获取用户信息验证n?br /> TestingAuthenticationProvider 单元试时?/p>
每个认证者会对自己指定的证明信息q行认证Q如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationTokenq个证明信息q行认证?/p>
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>
2) daoAuthenticationProvider
q行单的Z数据库的w䆾验证。DaoAuthenticationProvider获取数据库中的̎号密码ƈq行匚wQ若成功则在通过用户w䆾的同时返回一个包含授权信息的Authentication对象Q否则n份验证失败,抛出一个AuthenticatiionException?/p>
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="jdbcDaoImpl"/>
<property name="userCache" ref="userCache"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>
3) passwordEncoder
使用加密器对用户输入的明文进行加密。Acegi提供了三U加密器:
PlaintextPasswordEncoder—默认,不加密,q回明文.
ShaPasswordEncoder—哈希算?SHA)加密
Md5PasswordEncoder—消息摘?MD5)加密
<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
4) jdbcDaoImpl
用于在数据中获取用户信息?acegi提供了用户及授权的表l构Q但是您也可以自己来实现。通过usersByUsernameQueryq个SQL得到你的(用户ID,密码,状态信?;通过authoritiesByUsernameQueryq个SQL得到你的(用户ID,授权信息)
<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="usersByUsernameQuery">
<value>select loginid,passwd,1 from users where loginid = ?</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>select u.loginid,p.name from users u,roles r,permissions p,user_role ur,role_permis rp where u.id=ur.user_id and r.id=ur.role_id and p.id=rp.permis_id and
r.id=rp.role_id and p.status='1' and u.loginid=?</value>
</property>
</bean>
5) userCache & resourceCache
~存用户和资源相对应的权限信息。每当请求一个受保护资源ӞdaoAuthenticationProvider׃被调用以获取用户授权信息。如果每ơ都从数据库获取的话Q那代h很高Q对于不常改变的用户和资源信息来_最好是把相x权信息缓存v来?详见 2.6.3 资源权限定义扩展 )
userCache提供了两U实? NullUserCache和EhCacheBasedUserCache, NullUserCache实际上就是不q行M~存QEhCacheBasedUserCache是用Ehcache来实现缓功能?/p>
<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="userCache"/>
</bean>
<bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache" autowire="byName">
<property name="cache" ref="userCacheBackend"/>
</bean>
<bean id="resourceCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="resourceCache"/>
</bean>
<bean id="resourceCache" class="org.springside.modules.security.service.acegi.cache.ResourceCache" autowire="byName">
<property name="cache" ref="resourceCacheBackend"/>
</bean>
6) basicProcessingFilter
用于处理HTTP头的认证信息Q如从Springq程协议(如Hessian和Burlap)或普通的览器如IE,Navigator的HTTP头中获取用户信息Q将他们转交l通过authenticationManager属性装配的认证理器。如果认证成功,会将一个Authentication对象攑ֈ会话中,否则Q如果认证失败,会将控制转交l认证入口点(通过authenticationEntryPoint属性装?
<bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationEntryPoint" ref="basicProcessingFilterEntryPoint"/>
</bean>
7) basicProcessingFilterEntryPoint
通过向浏览器发送一个HTTP401(未授?消息Q提C用L录?br />处理ZHTTP的授权过E, 在当验证q程出现异常后的"d"Q通常实现转向、在response里加入error信息{功能?/p>
<bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
<property name="realmName" value="SpringSide Realm"/>
</bean>
8) authenticationProcessingFilterEntryPoint
当抛出AccessDeniedExceptionӞ用户重定向到登录界面。属性loginFormUrl配置了一个登录表单的URL,当需要用L录时QauthenticationProcessingFilterEntryPoint会将用户重定向到该URL
<bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl">
<value>/security/login.jsp</value>
</property>
<property name="forceHttps" value="false"/>
</bean>
1) httpSessionContextIntegrationFilter
每次request?HttpSessionContextIntegrationFilter从Session中获取Authentication对象Q在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前用,使之能跨多个请求?/p>
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>
<bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
2) httpRequestAccessDecisionManager
l过投票机制来决定是否可以访问某一资源(URL或方?。allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过。可选的决策机制有ConsensusBased和UnanimousBased
<bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
3) roleVoter
必须是以rolePrefix讑֮的value开头的权限才能q行投票,如AUTH_ , ROLE_
<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value="AUTH_"/>
</bean>
4Q?strong>exceptionTranslationFilter
异常转换qo器,主要是处理AccessDeniedException和AuthenticationExceptionQ将l每个异常找到合适的"d"
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"/>
</bean>
5) authenticationProcessingFilter
和servlet spec差不?处理登陆h.当n份验证成功时QAuthenticationProcessingFilter会在会话中放|一个Authentication对象Qƈ且重定向到登录成功页?br /> authenticationFailureUrl定义登陆p|时{向的面
defaultTargetUrl定义登陆成功时{向的面
filterProcessesUrl定义登陆h的页?br /> rememberMeServices用于在验证成功后dcookie信息
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl">
<value>/security/login.jsp?login_error=1</value>
</property>
<property name="defaultTargetUrl">
<value>/admin/index.jsp</value>
</property>
<property name="filterProcessesUrl">
<value>/j_acegi_security_check</value>
</property>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
6) filterInvocationInterceptor
在执行{向url前检查objectDefinitionSource中设定的用户权限信息。首先,objectDefinitionSource中定义了讉KURL需要的属性信?q里的属性信息仅仅是标志Q告诉accessDecisionManager要用哪些voter来投?。然后,authenticationManager掉用自己的provider来对用户的认证信息进行校验。最后,有投者根据用h有认证和讉Kurl需要的属性,调用自己的voter来投,军_是否允许讉K?/p>
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="objectDefinitionSource" ref="filterDefinitionSource"/>
</bean>
7) filterDefinitionSource (详见 2.6.3 资源权限定义扩展)
自定义DBFilterInvocationDefinitionSource从数据库和cache中读取保护资源及光要的讉K权限信息
<bean id="filterDefinitionSource" class="org.springside.modules.security.service.acegi.DBFilterInvocationDefinitionSource">
<property name="convertUrlToLowercaseBeforeComparison" value="true"/>
<property name="useAntPath" value="true"/>
<property name="acegiCacheManager" ref="acegiCacheManager"/>
</bean>
(详见 2.6.3 资源权限定义扩展)
1) methodSecurityInterceptor
在执行方法前q行拦截Q检查用h限信?br />2) methodDefinitionSource
自定义MethodDefinitionSource从cache中读取权?/p>
<bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="objectDefinitionSource" ref="methodDefinitionSource"/>
</bean>
<bean id="methodDefinitionSource" class="org.springside.modules.security.service.acegi.DBMethodDefinitionSource">
<property name="acegiCacheManager" ref="acegiCacheManager"/>
</bean>
采用 http://jcaptcha.sourceforge.net 作ؓ通用的验证码ҎQ请参考SpringSide中的例子Q或|上的:
http://www.coachthrasher.com/page/blog?entry=jcaptcha_with_appfuse?/p>
差沙在此q程中又发现acegi logout filter的错误,q行了修正?/p>
另外它默认提供的囄比较难认Q我们custom了一个美观一点的版本?/p>
本demo既适合于JSF + Spring2.0.1 + Hibernate3.2 目也适合于Struts + Spring2.0.1 + Hibernate3.2目Q?br />
未列入特别说明没有授权的企业和个人都可以自由免费下蝲使用提供宝贵意见Q?br />
本h不急功q利Q正在做完整的文档编写,做最后严格的试Q近期在此免费发布,敬请xQ?/p>