1.web.xml的配置
<filter >
<filter-name>securityFilter</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 >
FilterToBeanProxy就是Acegi过滤器Bean的代理,功能是把http请求按顺序分派给过滤器Bean;
说明:Acegi对WEB应用的支持主要是依靠servlet 过滤器(filter) 来实现的。每一个http request都将被这┕ 似鞑悴憷菇?并进行安全处理(包括认证和授权)。针对不同的安全处理,Acegi提供了不同的过滤器。过滤器的配置信息理论上应位于web.xml,但是我们又希望把Acegi的过滤器配置信息放在SpringFramework的配置文件里(applicationContext-security-acegi.xml),从而实现对这些过滤器的“控制反转”。解决这个问题的方法是采用Acegi提供的FilterToBeanProxy。FilterToBeanProxy顾名思义就是对Acegi过滤器Bean的代理,它的主要功能就是将http请求依次分派给对应的过滤器Bean。
这个Filter需要一个参数targetClass(目标类),意思是说代理哪个bean,为它配置的值是FilterChainProxy,就是由这个FilterChainProxy类负责将需要代理的这些Filter组成Filter代理“链”(这些Filter在Security.xml这个配置文件里以bean的形式进行配置了)
web.xml加入如下内容
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/j_security_check</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
这个就好理解了,就是这样的url都让他被securityFilter这个过滤器过滤处理
web.xml加入如下内容
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml</param-value>
</context-param>
这个就是让上下文载入/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml这些配置文件
2.security.xml的配置
首先加入filterChainProxy这个bean的定义,因为前面在web.xml配置的filter需要这个bean
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义了url比较前先转为小写, PATTERN_TYPE_APACHE_ANT定义了使用Apache ant的匹配模式
这个bean将httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor这些bean组成了filter链,当发生需要web.xml配置的过滤器的对应的需要过滤的url的请求时,这些filter将会按照定义的顺序被调用,这个过滤器的mapping是“/*”。
既然配置了这些需要被调用的给filterChainProxy,那么就要对这些filter进行逐个配置,以便filterChainProxy能找到并调用他们。
httpSessionContextIntegrationFilter的配置及作用
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
每次request前 HttpSessionContextIntegrationFilter从Session中获取Authentication对象并组装ContextHolder。ContextHolder主要用于存放SecureContext,包括用户的权限信息,在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前使用,使之能跨越多个请求。
authenticationProcessingFilter的配置及作用
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/login.jsp?error=true"/> 登录失败的url
<property name="defaultTargetUrl" value="/"/> 登录成功后的url
<property name="filterProcessesUrl" value="/j_security_check"/> 需要这个filter处理的url
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
该Filter负责处理登陆身份验证。当接受到与filterProcessesUrl所定义相同的请求时,它会首先通过 AuthenticationManager来验证用户身份。如果验证成功,则重定向到defaultTargetUrl所定义的成功登陆页面。如果验证失败,则再从rememberMeServices中获取用户身份,若再获取失败,则重定向到authenticationFailureUrl所定义登陆失败页面。
securityContextHolderAwareRequestFilter的配置及作用
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
该Filter负责通过Decorate Model(装饰模式),装饰的HttpServletRequest对象。其Wapper是ServletRequest包装类 HttpServletRequestWrapper的子类(SavedRequestAwareWrapper或 SecurityContextHolderAwareRequestWrapper),附上获取用户权限信息,request参数,headers, Date headers 和 cookies 的方法。
在appfuse中使用的struts-menu.xml对用户菜单权限的控制参数role进行配置时必须结合该Filter,因为该filter有isUserInRole方法,而struts menu也是通过request.isUserInRole方法来控制菜单是否显示的
RememberMeProcessingFilter的配置及作用
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="rememberMeServices" ref="rememberMeServices" />
</bean>
该Filter负责在用户登录后在本地机上记录用户cookies信息,免除下次再次登陆。检查AuthenticationManager 中是否已存在Authentication对象,如果不存在则会调用RememberMeServices的aotoLogin方法来从cookies中获取Authentication对象
AnonymousProcessingFilter的配置及作用
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="anonymous"/>
<property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
</bean>
该Filter负责为当不存在任何授权信息时,自动为Authentication对象添加userAttribute中定义的匿名用户权限
ExceptionTranslationFilter的配置及作用
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
<property name="forceHttps" value="false" />
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>
该过滤器负责处理各种异常,然后重定向到相应的页面中。
filterInvocationInterceptor的配置及作用
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/signup.html*=ROLE_ANONYMOUS,admin,user
/passwordHint.html*=ROLE_ANONYMOUS,admin,user
/**/*.html*=admin,user
/clickstreams.jsp*=admin
</value>
</property>
</bean>
或
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/> 认证服务
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value=""/> //这里定义数据库中存放的角色和我们在这里声明的角色间是否需要加个前缀?这里没加
</bean>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/admin.htm*=a 这里就是数据库中对应的tyep a
/student*=s 由于没有前缀和数据库里一样
/teacher*=t
</value>
</property>
</bean>
按照多数的ACEGI的配置文档,权限表的权限标识多以AUTH_或ROLE_开头,那么如果你的表中是这么存储的就可以在rolePrefix处配置一个开头标识(其实这仅仅是个标识,没有任何实际意义,appfuse就没有这么配置)
该过滤器会首先调用AuthenticationManager判断用户是否已登陆认证,如还没认证成功,则重定向到登陆界面。认证成功,则并从 Authentication中获取用户的权限。然后从objectDefinitionSource属性获取各种URL资源所对应的权限。最后调用 AccessDecisionManager来判断用户所拥有的权限与当前受保华的URL资源所对应的权限是否相匹配。如果匹配失败,则返回403错误 (禁止访问)给用户。匹配成功则用户可以访问受保护的URL资源。