iT邦幫忙

DAY 27
0

無痛學習SpringMVC與Spring Security系列 第 27

[Security]Method-Level Security(II)-@PostFilter篩選輸出條件

Method Security另外還有兩種Annotation: @RoleAllowed及Secured,前者follow JSR-250的標準,在Spring 2.x時就已支援,後者與前者類似,但僅支援對於使用者的Role作check,不支援Spring Expression Language,比起@PreAuthorize功能較為受限,之前的HttpSecurity對於Access Control便是使用Spring Expression Language,只不過在Spring Security中稱作SecurityExpressionRoot,支援的Expression可參考官網(http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#overview)。

在Spring Security中@pre- 及@post- 相關Annotation是應用到Spring Aspect Oriented Programming (AOP)的概念,AOP的實作要懂得術語不少如Advice、Pointcut、Before、After及Around等且相當有一定的難度,Spring Security已經提供相關實作,初學只要懂得如何使用即可,

相關annotation總共有四個,分別是@PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter,實際應用來看,我們會希望在執行某method之前進行Role的check(@PreAthorize),在執行某method後進行資訊過濾(@PostFilter),前者昨日已介紹,今日分享@PostFilter應用,兩者可以一起使用或是獨立使用,不衝突。

之前DCN Record只要確認登入後及會顯示所有紀錄,今天將透過@PostFilter使DCN清單只留下DCN的某欄位與登入的使用者名稱match的紀錄,在DCN.java中新增responsibleEngineer欄位,並手動新增資料庫中所有紀錄該欄位資料,

@Entity
public class DCN implements Serializable{
	
	private static final long serialVersionUID = 3716247587694820755L;

	......

	@Column
	private String responsibleEngineer;
	

	public String getResponsibleEngineer() {
		return responsibleEngineer;
	}
	public void setResponsibleEngineer(String responsibleEngineer) {
		this.responsibleEngineer = responsibleEngineer;
	}	
}

啟動Server,DCN清單畫面如下


可以看到每筆紀錄都有RE

接著更新DCNRepository,宣告@PostFilter於List<DCN> findAll()上,當List<DCN> findAll()方法執行完之後會回傳一個filterObject,如果回傳的是Collection,Spring會iterate每筆紀錄,並判斷@PostFilter裡的參數,若為true,該筆紀錄最後顯示於網頁上,其code如下

public interface DCNRepository{
	void save(DCN dcn);
	
	@PreAuthorize("hasRole('ROLE_USER')")
	@PostFilter("filterObject.responsibleEngineer == principal.username")//判斷RE是否為登入的使用者
	List<DCN> findAll();       //principal物件代表目前登入的使用者,該物件under在o.s.s.authentication底下
	
	DCN findByNo(String dcnNo);
	DCN findByNoAndRev(String dcnNo, Integer rev);
}

啟動Server,並以Patrick登入,網頁顯示只有RE為Patrick的紀錄

另外以John登入,可以看到只有RE為John的紀錄

或是換成另一個篩選條件

@PostFilter("filterObject.category == 'A' ")//篩選條件為Category為A

或許我的例子不是很好,但是透過@PreAuthorize及@PostFilter搭配不同的SecurityExpressionRoot,可以呈現依登入的使用者不同而看到不同的網頁資訊或是資料庫資料


上一篇
[Security]Method-Level Security(I)-@PreAuthorize的使用
下一篇
[Controller/Security]WebDataBinder-@InitBinder應用於表單欄位binding及表單驗證(Spring Vaildator)
系列文
無痛學習SpringMVC與Spring Security31

尚未有邦友留言

立即登入留言