後端基於方法的許可權控制--Spirng-Security
後端基於方法的許可權控制--Spirng-Security
預設情況下, Spring Security 並不啟用方法級的安全管控. 啟用方法級的管控後, 可以針對不同的方法通過註解設定不同的訪問條件;Spring Security 支援三種方法級註解, 分別是 JSR-205/Secured 註解/prePostEnabled。
開啟方法級別註解
<global-method-security secured-annotations="enabled" /> <global-method-security jsr250-annotations="enabled" /> <global-method-security pre-post-annotations="enabled" />
//@Secured 註解
@EnableGlobalMethodSecurity(securedEnabled=true)
//JSR-205 註解
@EnableGlobalMethodSecurity(jsr250Enabled=true)
//@PreAuthorize 型別的註解(支援 Spring 表示式)
@EnableGlobalMethodSecurity(prePostEnabled=true)
開始方法級別的註釋使用
Secured
只有滿足角色的使用者才能訪問被註解的方法, 否則將會丟擲 AccessDenied 異常.@Secured("ROLE_TELLER","ROLE_ADMIN"), 該方法只允許 ROLE_TELLER 或 ROLE_ADMIN 角色的使用者訪問.
@Secured("IS_AUTHENTICATED_ANONYMOUSLY"), 該方法允許匿名使用者訪問.JSR-205
@DenyAll
註解, 拒絕所有的訪問
@PermitAll
註解, 執行所有訪問
@RolesAllowed({"USER","ADMIN"})
, 該方法只允許有 ROLE_USER 或 ROLE_ADMIN 角色的使用者訪問.PreAuthorize
JSR-205 和 Secured 註解功能較弱, 不支援 Spring EL 表示式. 推薦使用 @PreAuthorize 型別的註解.@PreAuthorize 註解, 在方法呼叫之前, 基於表示式結果來限制方法的使用.
@PostAuthorize 註解, 允許方法呼叫, 但是如果表示式結果為 false, 將丟擲一個安全性異常.
@PostFilter 註解, 允許方法呼叫, 但必要按照表達式來過濾方法的結果.
@PreFilter 註解, 允許方法呼叫, 但必須在進入方法之前過來輸入值.
詳解PreAuthorize
表示式
- returnObject 保留名
對於 @PostAuthorize 和 @PostFilter 註解, 可以在表示式中使用 returnObject 保留名, returnObject 代表著被註解方法的返回值, 我們可以使用 returnObject 保留名對註解方法的結果進行驗證.
比如:
@PostAuthorize ("returnObject.owner == authentication.name")
public Book getBook();
@PostAuthorize 和 @PostFilter 本身在方法之後使用 ;本身使用場景不多
- 表示式中的 # 號
在表示式中, 可以使用 #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);
- 內建表示式有:
表示式 | 備註 |
---|---|
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) |