Acegi Security 是用於企業 Web 應用程序的一個強大、靈活的安全性解決方案。Acegi 構建在 Java EE 的聲明式安全性方法之上,並將 URL 和業務方法許可擴展至任意 Java 對象。Acegi Security 爲應用程序提供全面的身份驗證、受權、基於實例的訪問控制、通道安全和用戶驗證功能。
如何在現有框架中集成acegi
看了這麼牛的介紹,咱們要怎麼將acegi和咱們現有系統進行集成呢?
下面以小弟本身弄得一個springMVC框架爲例,看看如何一步一步來集成acegi
第一步:JAR包
一如既往,麻煩的jar包(在使用mvn以前我一直爲這個很頭疼,無止境的衝突),這裏我使用的0.9.0版的acegi-security
<dependency>
<groupId>org.acegisecurity</groupId>
<artifactId>acegi-security</artifactId>
<version>0.9.0</version>
</dependency>
若是你不是使用的mvn,不要緊,去下載一個好了。http://sourceforge.net/projects/acegisecurity/files/
第二部:配置
若是你不須要特殊的權限配置,基本上來講,配置就是你使用acegi的所有了:),讓咱們來看看怎麼配置吧。
beans-acegi-security.xml這個是我配置的acegi信息,你們能夠看到已經和Spring集成了.
html
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd" default-autowire="byName"> <bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter </value> </property> </bean> <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> <property name="allowSessionCreation" value="false" /> </bean> <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> </list> </property> </bean> <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="usersByUsernameQuery"> <value>SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1</value> </property> <property name="authoritiesByUsernameQuery"> <value>SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1</value> </property> </bean> <bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/> <bean id="acegiUserCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"> <property name="cache" ref="acegiCacheBackend" /> </bean> <bean id="acegiCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref bean="cacheManager"/> </property> <property name="cacheName"> <value>acegiCache</value> </property> </bean> <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager"> <ref bean="cacheManager"/> </property> <property name="cacheName"> <value>userCache</value> </property> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" > <property name="configLocation"> <value>classpath:/META-INF/config/ehcache.xml</value> </property> </bean> <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="authenticationDao" ref="jdbcDaoImpl" /> <property name="passwordEncoder" ref="passwordEncoder" /> <property name="userCache" ref="acegiUserCache" /> </bean> <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> <property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property> </bean> <bean id="filterInvocationInterceptor" class="net.sf.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 /logon.htm*=ROLE_ANONYMOUS,ROLE_USER /index.htm*=ROLE_ANONYMOUS,ROLE_USER /register.htm*=ROLE_ANONYMOUS,ROLE_USER /dwr/**=ROLE_ANONYMOUS,ROLE_USER /service/**=ROLE_ANONYMOUS,ROLE_USER /**=ROLE_USER </value> </property> </bean> <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"> <property name="allowIfAllAbstainDecisions"><value>false</value></property> <property name="decisionVoters"> <list> <ref bean="roleVoter"/> </list> </property> </bean> <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationFailureUrl"><value>/logon.htm?login_error=1</value></property> <property name="defaultTargetUrl"><value>/index.htm</value></property> <property name="filterProcessesUrl"><value>/user_login.htm</value></property> <property name="rememberMeServices"><ref bean="rememberMeServices"/></property> </bean> <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl"><value>/logon.htm</value></property> <property name="forceHttps"><value>false</value></property> </bean> <bean id="rememberMeServices" class="net.sf.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"> <property name="tokenValiditySeconds" value="432000"/> <property name="key" value="springRocks" /> <property name="authenticationDao" ref="jdbcDaoImpl" /> </bean> <bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> <property name="key" value="anonymous" /> <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS" /> </bean> </beans>
18個類的定義就支撐起了咱們的acegi安全框架,不得不讚嘆下acegi的牛人啊!
簡單說明下,若是須要更加具體的說明能夠google,也能夠去看下http://www.springside.org.cn/docs/reference/Acegi3.htm這裏介紹得比較詳細,不像蘭色說不清楚,嘿嘿!java
filterChainProxy:是經過一個標準的FilterInvocationDefinitionSource 來實現配置的,在這個類下面有filterInvocationDefinitionSource配置項目,裏面定義了一個過濾器的鏈,這決定了咱們在頁面上進行的任何一次請求均會通過這個過濾器鏈中全部過濾器的處理:)我定義的鏈比較簡單,就是用了httpSessionContextIntegrationFilter、authenticationProcessingFilter、anonymousProcessingFilter、securityEnforcementFilter四個過濾器,還有不少acegi過濾器就不一一列出了,有興趣的同窗能夠本身去參考一下其餘網絡資料或者書籍進行學習哦!
httpSessionContextIntegrationFilter:在多個請求之間共享SecurityContext,若是存在則必須放在過濾器鏈的第一位。用戶認證後負責從Session中獲取用戶關聯的SecurityContext存放到SecurityContextHolder,每一個請求都會有SecurityContextHolder用來保存着SecurityContext,而SecurityContext又保存了包含acegi認證重要信息的Authentication對象。
authenticationProcessingFilter:使用認證處理過濾器處理匹配的URL,這裏定義你的登陸頁面,成功跳轉頁面和失敗頁面,還能夠設置是否須要記錄登陸狀態等。
anonymousProcessingFilter:匿名用戶處理。若是用戶還沒有登陸,將生成一個匿名用戶的Authentication存放到SecurityContext中
securityEnforcementFilter:強制安全驗證過濾器。驗證所請求的url是否在用戶的權限範圍內web
第二部:數據庫綁定spring
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> <property name="providers"> <list> <ref bean="daoAuthenticationProvider" /> </list> </property> </bean> <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="authenticationDao" ref="jdbcDaoImpl" /> <property name="passwordEncoder" ref="passwordEncoder" /> <property name="userCache" ref="acegiUserCache" /> </bean> <bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="usersByUsernameQuery"> <value>SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1</value> </property> <property name="authoritiesByUsernameQuery"> <value>SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1</value> </property> </bean> <bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
上面的配置中,咱們設置了認證數據是由數據庫提供的,而且啓用了MD5對密碼進行加密和緩存,而後咱們還能夠看到兩條sql語句。
SELECT loginName as username,password,status as enabled FROM t_users WHERE loginName=? and status=1
SELECT loginName as username,authority FROM t_users WHERE loginName=? and status=1
這個是最基本的acegi的認證方式,須要提供的內容有
用戶信息:包括username(用戶名),password(密碼),enabled(開啓狀態)
認證信息:包括username(登錄名),authority(認證級別)
(上面的英文列名若是不擴展的話必須是同樣的哦,若是你當前數據庫中的字段名稱不同,請用as語句轉換一下才能用)
這個時候acegi就知道數據庫中咱們的用戶信息及權限級別了:)sql
第三步 那acegi怎麼控制用戶訪問呢?
數據庫
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property> <property name="authenticationEntryPoint"><ref bean="authenticationProcessingFilterEntryPoint"/></property> </bean> <bean id="filterInvocationInterceptor" class="net.sf.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 /logon.htm*=ROLE_ANONYMOUS,ROLE_USER /index.htm*=ROLE_ANONYMOUS,ROLE_USER /register.htm*=ROLE_ANONYMOUS,ROLE_USER /dwr/**=ROLE_ANONYMOUS,ROLE_USER /service/**=ROLE_ANONYMOUS,ROLE_USER /**=ROLE_USER </value> </property> </bean> <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased"> <property name="allowIfAllAbstainDecisions"><value>false</value></property> <property name="decisionVoters"> <list> <ref bean="roleVoter"/> </list> </property> </bean> <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> <bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> <property name="key" value="anonymous" /> <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS" /> </bean>
哈,上面的就是最基本的acegi的認證投票了,咱們定義了一個反問URL角色過濾器用來告訴acegi訪問url時候須要使用什麼角色,用了一個投票器告訴acegi處理訪問用戶須要使用默認的ROLE_開頭,從配置總咱們能夠看到兩種角色ROLE_ANONYMOUS、ROLE_USER,對應authority(認證級別)中存放的內容哦,還有一種ROLE_ANONYMOUS,這個是默認任何人均可以訪問的。緩存
第四步 都配好了,怎麼登錄?
安全
<bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationFailureUrl"><value>/logon.htm?login_error=1</value></property> <property name="defaultTargetUrl"><value>/index.htm</value></property> <property name="filterProcessesUrl"><value>/user_login.htm</value></property> <property name="rememberMeServices"><ref bean="rememberMeServices"/></property> </bean> <bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl"><value>/logon.htm</value></property> <property name="forceHttps"><value>false</value></property> </bean>
哈哈,有不少url頁面了!
filterProcessesUrl:用於認證的action
defaultTargetUrl投票認證成功後跳轉頁面
authenticationFailureUrl:投票認證失敗後跳轉頁面
loginFormUrl:認證失效用戶重定向到登錄的表單url
如今頁面url也配置好了,讓咱們再看看登錄頁面裏面有什麼呢?
網絡
<form action="user_login.htm" method="post"> <table border="1px" cellpadding="1" cellspacing="1" style="text-align: center"> #if($errMsg) <tr> <td colspan="3"><style color="red">$errMsg</style></td> </tr> #end <tr> <td>用戶名:</td> <td><input type="text" name="j_username"></td> <td> </td> </tr> <tr> <td>密 碼:</td> <td><input type="password" name="j_password"></td> <td> </td> </tr><tr> <td> </td> <td><input id="submit" type="submit" value="登陸" name="submit" /> <input id="submit" type="button" value="註冊" name="register" onClick="location.href='register.htm'"/></td> <td> </td> </tr> </table> </form>
一個form就搞定了,action是剛纔咱們配置的地址,用戶名和用戶密碼是默認的j_username,j_password這樣就能夠完成咱們的登陸了,你們能夠是嘗試一下
app