專欄丨Spring Security系列教程之Spring Security的四種許可權控制方式
原創:一一哥
前言:
在前面的章節中,一一哥 已經給大家介紹了Spring Security的很多功能,在這些眾多功能中,我們知道其核心功能其實就是認證+授權。
在前面我們分別基於記憶體模型、基於預設的資料庫模型、基於自定義資料庫模型實現了認證和授權功能,但是不管哪種方式,我們對某個介面的攔截限制,都是透過編寫一個SecurityConfig配置類,在該類的configure (Http Security http)方法中,透過http. authorize Requests ( ). antMatchers ("/admin/**")...這樣的程式碼進行的許可權控制。
這種許可權控制方法雖然也可以實現對某些介面的攔截或放行,但是不夠靈活,其實Spring Security對介面的攔截或放行的寫法,還有另外的方式,接下來請跟我學習一下吧!
一. 許可權控制方式
在Spring Security 中,我們既可以使用 Spring Security 提供的預設方式進行授權,也可以進行自定義授權,總之在Spring Security中許可權控制的實現方式是比較靈活多樣的。在Spring Security 中,對介面的攔截或放行,有四種常見的許可權控制方式:
利用Ant表示式實現許可權控制;
利用授權註解結合SpEl表示式實現許可權控制;
利用過濾器註解實現許可權控制;
利用動態許可權實現許可權控制。
對上面說到的四種許可權控制方式,我們接下來分別進行講解實現。
二. 利用Ant表示式實現許可權控制
利用Ant表示式的許可權控制方式,是我們之前一直在使用的許可權控制方式,在進行程式碼實現之前,我先對這種方式的底層實現進行簡單分析。
1. Spring Security中的許可權控制方法
在Spring Security中,有一個Security Expression Operations 介面,在該介面中定義了一系列的方法,用於使用者許可權的設定,如下圖:
SecurityExpressionOperations介面中的
這些方法作用如下圖所示:
2. Spring Security中的許可權控制粒度
這個介面有一個SecurityExpressionRoot子類,該類提供了基於表示式的許可權控制實現方式。而這個SecurityExpressionRoot 又有兩個實現子類,分別用於實現 URL Web介面粒度的許可權控制和方法粒度的許可權控制,如下圖所示:
3. 程式碼實現
從上面的小節中,我們知道在Spring Security中,支援2種粒度的許可權控制,即URL Web介面粒度 和方法粒度,而我們這裡所謂的 Ant表示式授權控制方式,就是透過Ant表示式來控制 URL 介面的訪問許可權。
那麼如果我們需要對URL介面粒度進行許可權控制,按如下程式碼即可實現:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**")
.hasRole("ADMIN")
.antMatchers("/user/**")
.hasRole("USER")
.antMatchers("/visitor/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.and()
//對跨域請求偽造進行防護---->csrf:利用使用者帶有登入狀態的cookie進行攻擊的手段
.csrf()
.disable();
}
以上程式碼中,/admin/ 格式的路徑需要 admin 角色才可以訪問,/user/ 格式的路徑需要 user 角色才可以訪問,/visitor/** 格式的路徑可以直接訪問,其他介面路徑則需要登入後才能訪問。
三. 利用授權註解結合SpEl表示式實現許可權控制
1. 授權註解
除了可以使用上面的Ant表示式進行授權實現,我們也可以在方法上新增授權註解來許可權控制,常用的授權註解有3個:
@PreAuthorize:方法執行前進行許可權檢查;
@PostAuthorize:方法執行後進行許可權檢查;
@Secured:類似於 @PreAuthorize。
2. 程式碼實現
要想利用以上3個授權註解進行許可權控制,我們首先需要利用@EnableGlobalMethodSecurity註解開啟授權註解功能,程式碼如下:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
...
}
然後在具體的介面方法上利用授權註解進行許可權控制,程式碼如下:
@RestController
public class UserController {
@Secured({"ROLE_USER"})
//@PreAuthorize("principal.username.equals('user')")
@GetMapping("/user/hello")
public String helloUser() {
return "hello, user";
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/hello")
public String helloAdmin() {
return "hello, admin";
}
@PreAuthorize("#age>100")
@GetMapping("/age")
public String getAge(@RequestParam("age") Integer age) {
return String.valueOf(age);
}
@GetMapping("/visitor/hello")
public String helloVisitor() {
return "hello, visitor";
}
}
可以看出,這種寫法明顯比利用Ant表示式進行許可權控制更靈活方便,所以開發時這種寫法很常用。
四. 利用過濾器註解實現許可權控制
1. 過濾器註解簡介
在Spring Security中還提供了另外的兩個註解,即@PreFilter和@PostFilter,這兩個註解可以對集合型別的引數或返回值進行過濾。使用@PreFilter和@PostFilter時,Spring Security將移除對應表示式結果為false的元素。
2. @PostFilter的用法
@PostFilter註解主要是用於對集合型別的返回值進行過濾,filterObject是@PostFilter中的一個內建表示式,表示集合中的元素物件。
@Slf4j
@RestController
public class FilterController {
/**
* 只返回結果中id為偶數的user元素。
* filterObject是@PreFilter和@PostFilter中的一個內建表示式,表示集合中的當前物件。
*/
@PostFilter("filterObject.id%2==0")
@GetMapping("/users")
public ListgetAllUser() {
Listusers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User(i, "yyg-" + i));
}
return users;
}
}
我們啟動瀏覽器進行測試,可以看到測試介面中只返回了id為偶數的元素。
3. @PreFilter的用法
使用@PreFilter也可以對集合型別的引數進行過濾,當@PreFilter標註的方法內擁有多個集合型別的引數時,可以透過@PreFilter的filterTarget屬性來指定當前是針對哪個引數進行過濾的;而filterObject是@PreFilter中的一個內建表示式,表示集合中的元素物件。
為了方便測試,我們在Service層中進行過濾操作,然後在Controller層中進行呼叫。
FilterService類中的方法定義:
@Slf4j
@Service
public class FilterService {
/**
* 當@PreFilter標註的方法內擁有多個集合型別的引數時,
* 可以透過@PreFilter的filterTarget屬性來指定當前是針對哪個引數進行過濾的。
*/
@PreFilter(filterTarget = "ids", value = "filterObject%2==0")
public ListdoFilter(Listids, Listusers) {
log.warn("ids=" + ids.toString());
log.warn("users=" + users.toString());
return ids;
}
}
在Controller中定義一個測試介面:
@Slf4j
@RestController
public class FilterController {
/**
* 只返回結果中id為偶數的user元素。
* filterObject是@PreFilter和@PostFilter中的一個內建表示式,表示集合中的當前物件。
*/
@PostFilter("filterObject.id%2==0")
@GetMapping("/users")
public ListgetAllUser() {
Listusers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User(i, "yyg-" + i));
}
return users;
}
@Autowired
private FilterService filterService;
@GetMapping("/users2")
public ListgetUserInfos() {
Listids = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ids.add(i);
}
Listusers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User(i, "yyg-" + i));
}
return filterService.doFilter(ids, users);
}
}
我們啟動瀏覽器進行測試,可以看到測試介面中只返回id為偶數的元素。
4. 程式碼結構
下圖是上面案例的程式碼結構,請參考實現:
五. 利用動態許可權實現許可權控制
我們知道一個標準的RABC, 許可權系統需要支援動態配置,Spring Security預設是在程式碼里約定好許可權,真實的業務場景裡通常需要可以支援動態配置角色訪問許可權,即在執行時去配置url對應的訪問角色。
而Spring Security中的動態許可權,主要是透過重寫攔截器和決策器來進行實現,最簡單的方法就是自定義一個Filter去完成許可權判斷。其實這裡涉及到的程式碼,基本和Spring Security關係不大,主要是在傳統的Filter進行實現,我這裡就不再進行描述了,感興趣的同學可以自行實現!
至此,我就給各位介紹了Spring Security中的4種進行許可權控制的方式,各位可以結合自己的專案需求進行選擇。
本文來自千鋒教育,轉載請註明出處。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31548651/viewspace-2840748/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 長沙Java培訓班分享:Spring教程之Spring Security的四種許可權控制方式JavaSpring
- Spring Security原始碼分析十三:Spring Security 基於表示式的許可權控制Spring原始碼
- spring security許可權認證Spring
- Spring Security實現統一登入與許可權控制Spring
- 基於RBAC的許可權控制淺析(結合Spring Security)Spring
- Spring Security 基於URL的許可權判斷Spring
- 基於 Spring Security 的前後端分離的許可權控制系統Spring後端
- 基於Spring Security實現許可權管理系統Spring
- Spring Security + jwt 許可權系統設計,包含SQLSpringJWTSQL
- Spring Security系列教程之一簡介Spring
- Security 10:許可權管理
- Spring Security實現基於RBAC的許可權表示式動態訪問控制Spring
- 基於Spring Security和 JWT的許可權系統設計SpringJWT
- Spring Security 許可權管理的投票器與表決機制Spring
- 專欄“殺青”丨千鋒一一哥Spring Security系列教程總結來咯!Spring
- Spring security(五)-完美許可權管理系統(授權過程分析)Spring
- Spring Security(四):更新前端路由獲取方式Spring前端路由
- Spring security(四)-spring boot +spring security簡訊認證+redis整合Spring BootRedis
- Spring Security原始碼分析二:Spring Security授權過程Spring原始碼
- Spring Security系列之授權過程(七)Spring
- 【Spring Security】實現多種認證方式Spring
- 基於Spring Security Oauth2的SSO單點登入+JWT許可權控制實踐SpringOAuthJWT
- 後端基於方法的許可權控制--Spirng-Security後端
- SpringBoot整合Spring security JWT實現介面許可權認證Spring BootJWT
- 最新版 Spring Security,該如何實現動態許可權管理?Spring
- Security8:許可權模擬
- 使用Spring Security控制會話Spring會話
- Spring Security系列之退出(十三)Spring
- Spring SecuritySpring
- RBAC許可權---SpringBoot整合SecuritySpring Boot
- Spring Security原始碼分析八:Spring Security 退出Spring原始碼
- spring security 授權方式(自定義)及原始碼跟蹤Spring原始碼
- Spring Boot —— Spring SecuritySpring Boot
- Spring Security系列之Session管理(十四)SpringSession
- Java Web系列:Spring Security 基礎JavaWebSpring
- Spring Security系列教程之實現CAS單點登入上篇-概述Spring
- Spring Security原始碼分析九:Spring Security Session管理Spring原始碼Session
- Spring Security系列之核心過濾器原始碼分析(四)Spring過濾器原始碼