Spring Security 之 @EnableGlobalMethodSecurity 方法級安全

默認情況下, Spring Security 並不啓用方法級的安全管控. 啓用方法級的管控後, 可以針對不同的方法通過註解設置不同的訪問條件.

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

Spring Security 支持三種方法級註解, 分別是 JSR-205 註解/@Secured 註解/prePostEnabled註解. 這些註解不僅可以直接加 controller 方法上, 也可以註解 Service 或 DAO 類中的方法. 

啓用方法級的管控代碼是, 新建一個 WebSecurityConfigurerAdapter Configuration 類, 加上 @EnableGlobalMethodSecurity() 註解, 通過@EnableGlobalMethodSecurity 參數開啓相應的方法級的管控.

===================================
JSR-205 註解
===================================
通過 @EnableGlobalMethodSecurity(jsr250Enabled=true), 開啓 JSR-205 註解.

@DenyAll 註解, 拒絕所有的訪問
@PermitAll 註解, 運行所有訪問
@RolesAllowed({"USER","ADMIN"}), 該方法只允許有 ROLE_USER 或 ROLE_ADMIN 角色的用戶訪問.


===================================
@Secured 註解
===================================
通過 @EnableGlobalMethodSecurity(securedEnabled=true), 開啓 @Secured 註解.
只有滿足角色的用戶才能訪問被註解的方法, 否則將會拋出 AccessDenied 異常.
例子:
@Secured("ROLE_TELLER","ROLE_ADMIN"), 該方法只允許 ROLE_TELLER 或 ROLE_ADMIN 角色的用戶訪問.
@Secured("IS_AUTHENTICATED_ANONYMOUSLY"), 該方法允許匿名用戶訪問.


===================================
@PreAuthorize 類型的註解(支持 Spring 表達式)
===================================
@EnableGlobalMethodSecurity(prePostEnabled=true), 開啓 prePostEnabled 相關的註解.
JSR-205 和 @Secured 註解功能較弱, 不支持 Spring EL 表達式. 推薦使用 @PreAuthorize 類型的註解.


具體有4個註解.
@PreAuthorize 註解, 在方法調用之前, 基於表達式結果來限制方法的使用.
@PostAuthorize 註解, 允許方法調用, 但是如果表達式結果爲 false, 將拋出一個安全性異常.
@PostFilter 註解, 允許方法調用, 但必要按照表達式來過濾方法的結果.
@PreFilter 註解, 允許方法調用, 但必須在進入方法之前過來輸入值.

 

例子:

@PreAuthorize("hasRole('ADMIN')") //必須有 ROLE_ADMIN 角色
public void addBook(Book book);

//必須同時具備 ROLE_ADMIN 和 ROLE_DBA 角色
@PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
public void addBook(Book book);


@PreAuthorize ("#book.owner == authentication.name")
public void deleteBook(Book book);


@PostAuthorize ("returnObject.owner == authentication.name")
public Book getBook();

===================================
@PreAuthorize 表達式
===================================
1. returnObject 保留名
對於 @PostAuthorize 和 @PostFilter 註解, 可以在表達式中使用 returnObject 保留名, returnObject 代表着被註解方法的返回值, 我們可以使用 returnObject 保留名對註解方法的結果進行驗證.

@PostAuthorize ("returnObject.owner == authentication.name")
public Book getBook();

2. 表達式中的 # 號
在表達式中, 可以使用 #argument123 的形式來代表註解方法中的參數 argument123.

@PreAuthorize ("#book.owner == authentication.name")
public void deleteBook(Book book);

還有一種 #argument123 的寫法, 即使用 Spring Security @P註解來爲方法參數起別名, 然後在 @PreAuthorize 等註解表達式中使用該別名. 不推薦這種寫法, 代碼可讀性較差.

@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);


3. 內置表達式有:

表達式 備註
hasRole([role]) 如果有當前角色, 則返回 true(會自動加上 ROLE_ 前綴)
hasAnyRole([role1, role2]) 如果有任一角色即可通過校驗, 返回true,(會自動加上 ROLE_ 前綴)
hasAuthority([authority]) 如果有指定權限, 則返回 true
hasAnyAuthority([authority1, authority2]) 如果有任一指定權限, 則返回true
principal  獲取當前用戶的 principal 主體對象 
authentication  獲取當前用戶的 authentication 對象, 
permitAll   總是返回 true, 表示全部允許
denyAll  總是返回 false, 代表全部拒絕
isAnonymous()  如果是匿名訪問, 返回true
isRememberMe()  如果是remember-me 自動認證, 則返回 true
isAuthenticated()  如果不是匿名訪問, 則返回true
isFullAuthenticated()  如果不是匿名訪問或remember-me認證登陸, 則返回true
hasPermission(Object target, Object permission)  
hasPermission(Object target, String targetType, Object permission)   
   

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章