我幾年前自己寫過一個后臺權限管理的東西,也是基于用戶-角色-權限這樣的結構,說實話代碼結構寫得不好,因為是硬編碼的形式,雖然功能其實用起來 還是挺好用的,用戶、角色及權限的管理均可在后臺輕松完成,但現在如果再用硬編碼的形式寫這樣的系統就說不過去了。目前關于權限管理的java開源系統比 較多,有的比較有名,有的不出名,比如像Spring Security就很出名,在權限管理方面做得也非常全面,子猴這篇文章也是對Spring Security做個簡短介紹。
我以最新版的spring-security-3.0.2作為介紹對象,如果你了解Spring 2.0 Security的話,那就比較抱歉了,因為spring-security-3.0.2與2.0相比改動很大,在2.0中的一些配置拿到3.0幾乎是行 不通的,如果你還沒有接觸過spring,那么以下是其地址:
Spring官方網址: http://www.springsource.org/
spring-security下載地址:
http://static.springsource.org/spring-security/site/downloads.html
我以其自帶的一個簡單例子來介紹一下吧,因為這個例子配置不對的話極易報錯(這個例子是個打包的War文件,但與文檔中的又不一樣,所以極易出錯),我會對出現的錯誤給予出錯原因及解決方法。
首先通過spring-security地址下載到最新版的spring-security-3.0.2.RELEASE.zip,然后解壓開來,在解壓開的目錄dist中,你會看到如下一些文件:
看到spring-security-samples-tutorial-3.0.2.RELEASE.war了嗎?我就以這個為例,把這個包拷貝 到你Web服務器(如Tomcat)的webapps目錄下,啟動服務器后,會生成一個spring-security-samples- tutorial-3.0.2.RELEASE項目,可以把名字改短一點方便訪問,比如我這里改名為:spring-security,這樣通過 http://127.0.0.1/spring-security 可以直接訪問了。
進入目錄WEB-INF,可以看到如上的一些文件,其中,applicationContext-security.xml是權限控制配置文件,所 有的權限控制都是在其中配置的,bank-servlet.xml是系統的上下文配置文件,可以在其中配置訪問路徑映射(類似于Struts-1.x中的 struts-config.xml或struts-2.x中的struts.xml文件),也可以在其中進行一些裝配等工作,屬于spring級的,與 安全配置沒多大關系。
具體的文件內容我就不展示了,因為可以自己打開看,我這里只說要注意的一些地方:
1、在web.xml中的配置
服務啟動時加載applicationContext-security.xml文件:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext-security.xml </param-value> </context-param>
要過濾鏈接的形式
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
你一定注意到了,這里的filter-class與Spring2.0的不同之處,如果你了解Spring2.0的話,的確,在Spring2.0中為:
<filter-name>acegiFilterChain</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
這就是3.0與2.0改變很大的一個地方,2.0用的為Acegi,后來Acegi嵌入到了Spring中,成為了Spring Security,所以包的路徑也都改變了!
2、在applicationContext-security.xml中的配置
<http use-expressions="true"> <intercept-url pattern="/secure/extreme/**" access="hasRole('ROLE_SUPERVISOR')"/> <intercept-url pattern="/secure/**" access="isAuthenticated()" /> <!-- Disable web URI authorization, as we're using <global-method-security> and have @Secured the services layer instead <intercept-url pattern="/listAccounts.html" access="isRememberMe()" /> <intercept-url pattern="/post.html" access="hasRole('ROLE_TELLER')" /> --> <intercept-url pattern="/**" access="permitAll" /> <form-login /> <logout /> <remember-me /> <!-- Uncomment to enable X509 client authentication support <x509 /> --> <!-- Uncomment to limit the number of sessions a user can have --> <session-management invalid-session-url="/timeout.jsp"> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> </http>
上面這段是初用者比較容易出錯的地方 ,這其實也是寫這篇文章的主要原因之一,注意到第一行的黑體字:
<http use-expressions=”true”>
表示這里的配置可以使用一種表達式,這種表達式就是類似于isAuthenticated()這樣的寫法,在后面會看到與這種寫法不一樣但同樣可以達到相同效果的寫法。
intercept-url表示要攔截的url形式,比如
<intercept-url pattern=”/secure/**” access=”isAuthenticated()” />
表示根目錄下的secure目錄需要經過驗證后才能訪問的。
<form-login />是Spring Security自動為你生成的一個簡陋的登錄頁面,即使你沒有創建任何登錄頁面,當然你也可以修改,但不建議你修改,因為你可以不使用默認的,可以采用 如下方式:<form-login login-page=’/ login.html’/>自定義一個登錄頁面。
其他的說明可以參考一個翻譯的中文文檔:
http://www.family168.com/tutorial/springsecurity3/html/ns-config.html
3、容易出錯的地方
在上面的翻譯文檔(也是翻譯自官方文檔)或英文官方文檔中,給出的與上面例子功能相似的說明大概是這樣的:
? <http auto-config='true'>
??? <intercept-url pattern="/**" access="ROLE_USER" />
? </http>
注意到與上面例子不同的地方了嗎?
還是注意第一行,這回不是 <http use-expressions=”true”> 而是 <http auto-config=’true’> 了,而下面的配置
<intercept-url pattern=”/**” access=”ROLE_USER” />也與上面的寫法不同,事實上如果是 <http use-expressions=”true”> 的話,這句 access=”ROLE_USER” 就是錯的,正確的寫法就應該為:hasRole(‘ROLE_USER’)。
這不得不說這是Spring Security的文檔與例子不搭配的一個低級錯誤,因為當一個使用者在打開例子又看到文檔說明時,他往往不知道這兩者有何區別,就如同我剛使用的時候一樣,我在使用 <http use-expressions=”true”> 的同時,將 access=”ROLE_USER” 這種寫法也寫了進來,結果可想而知,報了錯!報錯信息諸如:
org.apache.jasper.JasperException: java.lang.IllegalArgumentException: Failed to evaluate expression 'ROLE_SUPERVISOR'
就是說 use-expressions 這種表示法是不認識 access=”ROLE_USER” 這種寫法的,另外,當使用了 <http use-expressions=”true”> 時,一定要在配置中至少有一個符合 use-expressions 的表示法,否則就會報類似如下錯誤:
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'ROLE_SUPERVISOR' cannot be found on object of type 'org.springframework.security.web.access. expression.WebSecurityExpressionRoot'
這個簡單的配置例子大概就寫這么多吧,最后說說我對Spring Security的看法,我個人覺得Spring Security的功能的確是很強大,考慮得也非常全面,幾乎什么都想替使用者做完,但正是它的這點,我覺得倒是它的缺點,在我了解它并配置的過程中,我 個人覺得是非常復雜繁瑣的,而且它現在的文檔支持也并不好,正如上面所看到的一樣,文檔與例子中的寫法都不一致。事實上,使用者并不希望它什么都做到,比 如它做的那個缺省登錄頁面,那個有意義嗎?使用者比如我,其實就是希望一個很簡單的權限判斷,比如我打開某一個鏈接,然后你告訴我訪問者有無權限訪問,給 我返回一個類似true或false的結果就夠了!至于其他的事情,我是如何的處理后續過程并不用Spring Security操心的,但很顯然,子猴認為Spring Security在這點上做得并不好。
?
本文出自:http://www.zihou.me/2010/04/24/2081/
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
