添加@PreAuthorize方法註解
我們第一個的設計決策就是要在業務層上添加方法安全,以保證用戶在修改密碼前已經作爲系統的合法用戶進行了登錄。這通過爲業務接口方法定義添加一個簡單的註解來實現,如下:
這就是保證合法、已認證的用戶才能訪問修改密碼功能所要做的所有事情。Spring Security將會使用運行時的面向方面編程的切點(aspect oriented programming (AOP) pointcut)來對方法執行before advice,並在安全要求未滿足的情況下拋出AccessDeniedException異常。
讓Spring Security能夠使用方法註解
我們還需要在dogstore-security.xml中做一個一次性的修改,通過這個文件我們已經進行了Spring Security其他的配置。只需要在<http>聲明之前,添加下面的元素即可:
校驗方法安全
不相信如此簡單?那我們將ROLE_USER聲明修改爲ROLE_ADMIN。現在用用戶guest(密碼guest)登錄並嘗試修改密碼。你會在嘗試修改密碼時,看到如下的出錯界面:
如果查看Tomcat的控制檯,你可以看到很長的堆棧信息,開始是這樣的:
基於訪問拒絕的頁面以及指向changePassword方法的堆棧信息,我們可以看到用戶被合理的拒絕對業務方法的訪問,因爲缺少ROLE_ADMIN的GrantedAuthority。你可以測試修改密碼功能對管理員用戶依舊是可以訪問的。
我們只是在接口上添加了簡單的聲明就能夠保證方法的安全,這是不是太令人興奮了?當然,我們不會願意Tomcat 原生的403錯誤頁面在我們的產品應用中出現——我們將會在第六章:高級配置與擴展講述訪問拒絕處理時,對其進行更新。
讓我們介紹一下實現方法安全的其它方式,然後進入功能的背後以瞭解其怎樣以及爲什麼能夠生效。
幾種實現方法安全的方式
除了@PreAuthorize註解以外,還有幾種其它的方式來聲明在方法調用前進行授權檢查的需求。我們會講解這些實現方法安全的不同方式,並比較它們在不同環境下的優勢與不足。
遵守JSR-250標準規則
JSR-250, Common Annotations for the Java Platform定義了一系列的註解,其中的一些是安全相關的,它們意圖在兼容JSR-250的環境中很方便地使用。Spring框架從Spring 2.x釋放版本開始就兼容JSR-250,包括Spring Security框架。
儘管JSR-250註解不像Spring原生的註解富有表現力,但是它們提供的註解能夠兼容不同的Java EE應用服務器實現如Glassfish,或面向服務的運行框架如Apache Tuscany。取決於你應用對輕便性的需求,你可能會覺得犧牲代碼的輕便性但減少對特定環境的要求是值得的。
要實現我們在第一個例子中的規則,我們需要作兩個修改,首先在dogstore-security.xml文件中:
其次,@PreAuthorize註解需要修改成@RolesAllowed註解。正如我們可能推斷出的那樣,@RolesAllowed註解並不支持SpEL表達式,所以它看起來很像我們在第二節中提到的URL授權。我們修改IuserService定義如下:
正如前面的練習那樣,如果不相信它能工作,嘗試修改ROLE_USER 爲ROLE_ADMIN並進行測試。
要注意的是,也可以提供一系列允許的GrantedAuthority名字,使用Java 5標準的字符串數組註解語法:
JSR-250還有兩個其它的註解:@PermitAll 和@DenyAll。它們的功能正如你所預想的,允許和禁止對方法的任何請求。
【類層次的註解。注意方法級別的安全註解也可以使用到類級別上!如果提供了方法級別的註解,將會覆蓋類級別的註解。如果業務需要在整個類上有安全策略的話,這會非常有用。要注意的是使用這個功能要有良好的註釋的編碼規範,這樣開發人員能夠很清楚的瞭解類和方法的安全特性。】
我們將會在本章稍後的練習中介紹如何實現JSR-250風格的註解與Spring Security風格 的註解並存。
@Secured註解實現方法安全
Spring本身也提供一個簡單的註解,類似於JSR-250 的@RolesAllowed註解。@Secured註解在功能和語法上都與@RolesAllowed一致。唯一需要注意的不同點是要使用這些註解的話,要在<global-method-security>元素中明確使用另外一個屬性:
使用Aspect Oriented Programming (AOP)實現方法安全
實現方法安全的最後一項技術也可能是最強大的方法,它還有一個好處是不需要修改源代碼。作爲替代,它使用面向方面的編程方式爲一個方法或方法集合聲明切點(pointcut),而增強(advice)會在切點匹配的情況下進行基於角色的安全檢查。AOP的聲明只在Spring Security的XML配置文件中並不涉及任何的註解。
以下就是聲明保護所有的service接口只有管理權限才能訪問的例子:
切點表達式基於Spring AOP對AspectJ的支持。但是,Spring AspectJ AOP僅支持AspectJ切點表達式語言的一個很小子集——可以參考Spring AOP的文檔以瞭解其支持的表達式和其它關於Spring AOP編程的重要元素。
注意的是,可以指明一系列的切點聲明,以指向不同的角色和切點目標。以下的就是添加切點到DAO中一個方法的例子:
注意在新增的切點中,我們添加了一些AspectJ的高級語法,來聲明Boolean邏輯以及其它支持的切點,而參數可以用來確定參數的類型聲明。
同Spring Security其它允許一系列安全聲明的地方一樣,AOP風格的方法安全是按照從頂到底的順序進行的,所以需要按照最特殊到最不特殊的順序來寫切點。
使用AOP來進行編程即便是經驗豐富的開發人員可能也會感到迷惑。如果你確定要使用AOP來進行安全聲明,除了Spring AOP的參考手冊外,強烈建議你參考一些這個專題相關的書籍。AOP實現起來比較複雜,尤其是在解決不按照你預期運行的配置錯誤時更是如此。
比較方法授權的類型
以下的快速參考表可能在你選擇授權方法檢查時派上用場:
方法授權類型 |
聲明方式 |
JSR標準 |
允許SpEL表達式 |
@PreAuthorize @PostAuthorize |
註解 |
No |
Yes |
@RolesAllowed @PermitAll @DenyAll |
註解 |
Yes |
NO |
@Secure |
註解 |
No |
No |
protect-pointcut |
XML |
No |
No |
大多數使用Java 5的Spring Security用戶傾向於使用JSR-250註解,以達到在IT組織間最大的兼容性和對業務類(以及相關約束)的重用。在需要的地方,這些基本的聲明能夠被Spring Security本身實現的註解所代替。
如果你在不支持註解的環境中(Java 1.4或更早版本)中使用Spring Security,很不幸的是,關於方法安全的執行你的選擇可能會很有限。即使在這樣的情況下,對AOP的使用也提供了相當豐富的環境來開發基本的安全聲明。
原文 http://sishuok.com/forum/blogCategory/showByCategory.html?categories_id=77&user_id=2