環境:
struts2,acegi1.0.6,spring2.5.1,cas3
一、綜述:環境搭建
1.spring和acegi版本
spring2.5.6和acegi1.0.6兼容性問題
會報
java.lang.NoClassDefFoundError: org/springframework/web/bind/RequestUtils
不過據說裝合適的spring-webmvc這個jar也可以解決問題,沒有測試
1.搭建acegi環境
web.xml配置,使用acegi的過濾器
配置web.xml
<context-param>中包含新配置文件
<!-- Acegi過濾器 -->
<filter>
<filter-name>acegiFilterChain</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>
<!-- Acegi過濾器URL映射 -->
<filter-mapping>
<filter-name>acegiFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
過濾器要放在struts前面,否則會報錯。因為有些操作要acegi中的springmvc處理
javax.servlet.ServletException: Filter execution threw an exception
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:389)
java.lang.NoClassDefFoundError: org/springframework/web/bind/RequestUtils
配置acegi配置文件,配置認證管理器、投票管理器、過濾器鏈、配置acegi的log4j日志
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
========================================================================
認證管理器
=========================================================================
-->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref bean="daoAuthenticationProvider" />
<ref bean="rememberMeAuthenticationProvider" />
</list>
</property>
</bean>
<bean id="daoAuthenticationProvider"
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService" />
<property name="userCache" ref="userCache" />
</bean>
<!-- 基於DAO驗證的Ehcache實現 -->
<bean id="userCache"
class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache" ref="userCacheBackend" />
</bean>
<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName">
<value>userCache</value>
</property>
</bean>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="rememberMeAuthenticationProvider"
class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="remember_Me" />
</bean>
<!-- 使用數據庫DAO查找用戶和角色 -->
<bean id="userDetailsService" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
<property name="usersByUsernameQuery">
<value>
<![CDATA[SELECT u.staffname USERNAME,u.staffpwd PASSWORD,u.STATUS enabled FROM sw_staff u where u.STATUS = 1 AND u.staffname = ?]]>
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
<![CDATA[SELECT t1.staffid USERNAME,t3.roledec authority FROM sw_staff t1, SW_UserPower t2,sw_Roles t3 WHERE t1.staffid= t2.staffid and t2.roleid= t3.roleid and t1.staffname = ?]]>
</value>
</property>
</bean>
<!--
========================================================================
決策管理器
=========================================================================
-->
<!-- 至少有一個投票者容許,就可以訪問資源 -->
<bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter" />
</list>
</property>
<!-- 所有投票者棄權,不容許訪問 -->
<property name="allowIfAllAbstainDecisions" value="false" />
</bean>
<!--
========================================================================
過濾器鏈
=========================================================================
-->
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter
</value>
</property>
</bean>
<!-- 從Session中獲得用戶信息並放入SecurityContextHolder -->
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter" />
<!-- 用戶注銷 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<!-- 注銷后默認的跳轉頁面 -->
<constructor-arg value="/helloWorld.jsp" />
<constructor-arg>
<list>
<ref bean="rememberMeServices" />
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/j_logout.do" />
</bean>
<!-- 表單方式驗證用戶身份 -->
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 登錄失敗的頁面,包含出錯信息的登錄頁面 -->
<property name="authenticationFailureUrl" value="/login.jsp?login_error=Login%20failed." />
<!-- 登錄后的跳轉頁面 -->
<property name="defaultTargetUrl" value="/helloWorld.jsp" />
<!-- 用戶登錄的URL -->
<property name="filterProcessesUrl" value="/j_acegi_security_check" />
<property name="rememberMeServices" ref="rememberMeServices" />
</bean>
<bean id="casProcessingFilter" class="org.acegisecurity.ui.cas.CasProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 登錄后的跳轉頁面 -->
<property name="defaultTargetUrl" value="/helloWorld.jsp" />
<property name="filterProcessesUrl" value="/j_acegi_cas_security_check" />
<!-- 認證失敗后的跳轉頁面 -->
<property name="authenticationFailureUrl" value="/login.jsp?login_error=Login%20failed." />
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<!-- 記住用戶登錄信息 -->
<!--<bean id="rememberMeFilter"
class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="rememberMeServices" ref="rememberMeServices" />
</bean>
-->
<!-- 處理登錄異常或權限異常的Filter -->
<bean id="exceptionFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<!-- 出現AuthenticationException時的登錄入口,無認證異常 -->
<!--
表單登錄時用 <property name="authenticationEntryPoint"> <bean
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
將用戶導向登錄頁面 <property name="loginFormUrl" value="/login.jsp" />
是否強制使用https <property name="forceHttps" value="false" /> </bean>
</property>
-->
<!--CAS認證登錄時用-->
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
<property name="loginUrl"
value="https://localhost:8443/cas-server-webapp-3.1.1/login" />
<property name="serviceProperties" ref="serviceProperties" />
</bean>
</property>
<!-- 出現AccessDeniedException時的Handler,無權限異常-->
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>
<bean id="serviceProperties" class="org.acegisecurity.ui.cas.ServiceProperties">
<!-- CAS登錄后的重定向頁面-->
<property name="service" value="http://localhost:8080/test" />
<property name="sendRenew" value="false" />
</bean>
<bean id="securityInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/index.jsp=ROLE_LOGIN
/*action=ROLE_LOGIN
</value>
</property>
</bean>
說明:
1、過濾器鏈:filterChainProxy,有順序要求
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,rememberMeFilter,exceptionFilter,securityInterceptor
2、rememberMe配置要點
rememberMeServices使用TokenBasedRememberMeServices,token64編碼后放入cookie
logoutFilter使用rememberMeServices,離開后保存cookie
rememberMeFilter配置authenticationManager和rememberMeServices
rememberMeServices的parameter和html表單的Remember Me字段的name一致
rememberMeServices的key和authenticationManager中的rememberMeAuthenticationProvider的key要一致
3、使用DaoAuthenticationProvide實現基於數據庫的用戶認證授權,userDetailsService中可以用注入sql使用數據庫實現,文件方式保存用戶基本沒啥用
修改usersByUsernameQuery和authoritiesByUsernameQuery注入sql
使用Ehache提高性能
4、配置日志
<!-- 監聽認證授權事件,輸出日志 -->
<bean id="authenticationLoggerListener"
class="org.acegisecurity.event.authentication.LoggerListener" />
<bean id="authorizationLoggerListener"
class="org.acegisecurity.event.authorization.LoggerListener" />
對應的,如果是log4j.xml
log4j.xml
<logger name="log4j.logger.org.acegisecurity" additivity="true">
<level value="DEBUG" />
<appender-ref ref="LOG.DEBUG" />
</logger>
如果是log4j.properties
log4j.properties
log4j.logger.org.acegisecurity=DEBUG
5.表單認證
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<!-- 登錄失敗的頁面,包含出錯信息的登錄頁面 -->
<property name="authenticationFailureUrl" value="/login.jsp?login_error=Login%20failed." />
<!-- 登錄后的跳轉頁面 -->
<property name="defaultTargetUrl" value="/helloWorld.jsp" />
<!-- 用戶登錄的URL -->
<property name="filterProcessesUrl" value="/j_login.do" />
<property name="rememberMeServices" ref="rememberMeServices" />
</bean>
表單中的username和password的name這里為j_username和j_password,acegi的springmvc實現中用
filterProcessesUrl默認是j_acegi_security_check,可以修改,需要登錄頁面同步
6.用戶注銷
logoutFilter中filterProcessesUrl默認是j_acegi_logout,只要將退出頁面中url設置為j_acegi_logout就可以觸發
7.授權
accessDecisionManager:事前評估。使用投票表決器。RoleVoter是基於角色的投票表決器。
這里securityInterceptor使用文件配置,也可以修改為數據庫方式實現
8.使用aop對方法授權
第二部分:介紹dbms實現鑒權,包括資源過濾和方法過濾,表結構模型
第三部門:和CAS集成,包括CAS環境搭建,acegi集成CAS