文章目錄
前言
在上一篇文章已經介紹了springSecurity的使用了,本篇文章主要介紹一下使用spring EL表達式來控制授權,允許在表達式中使用複雜的布爾邏輯來控制訪問的權限
常見的表達式
Spring Security可用表達式對象的基類是SecurityExpressionRoot
表達式 | 描述 |
hasRole([role]) | 用戶擁有指定的角色時返回true(hasRole()默認會將配置中的 role 帶有 ROLE_ 前綴再和用戶的角色權限 進行對比) |
hasAnyRole([role1,role2]) | 用戶擁有任意一個指定中的角色時返回true |
hasAuthority([auth]) | 同hasRole()但不添加前綴 ROLE_ |
hasAnyAuthority([auth1,auth2]) | 同hasAnyRole([auth1,auth2]),但不添加前綴 ROLE_ |
permitAll | 永遠返回true |
denyAll | 永遠返回false |
anonymous | 當前用戶時 anonymous(匿名、未認證)時返回true |
rememberMe | 當前用戶時 rememberMe(記住登錄) 時發揮true |
authentication | 當前登錄用戶的 authentication 對象 |
fullAuthticated | 當前用戶既不是 anonymous 也不是 rememberMe 時返回true(即正常認證登錄時返回true) |
hasIpAddress("192.168.1.0/24") | ip匹配時返回true |
如果需要移除hasRole的前綴,在security配置類中添加如下代碼
@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults(){
return new GrantedAuthorityDefaults("");//remove the ROLE_ prefix
}
URL安全表達式
http.antMatchers("/test/*").access("hasRole('ADMIN') or hasRole('USER')")
.anyRequest().authenticated();
這裏我們定義了 /test/
URL的範圍,只有擁有 ADMIN
或 USER
權限的用戶可以訪問 /test/
匹配的URL
在Web 安全表達式中引用Bean自定義鑑權
http.antMatchers("/test/*").access("hasRole('ADMIN') or hasRole('USER')")
.antMatchers("/test/{id}").access("@rbacauthorityservice.checkTestId(authentication,#id)")//可以傳遞參數
.anyRequest()
.access("@rbacauthorityservice.hasPermission(request,authentication)");
rbacauthorityservice
@Component("rbacauthorityservice")
@Slf4j
public class Rbacauthorityservice {
/**
* uri匹配工具
*/
private AntPathMatcher antPathMatcher = new AntPathMatcher();
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
log.info("【Rbacauthorityservice】 --hasPermission={}", authentication.getPrincipal());
Object principal = authentication.getPrincipal();
//根據自己的業務來
boolean hasPermission = false;
//有可能是匿名的anonymous
if (principal instanceof SysUser) {
//admin永遠放回true
if (StringUtils.equals("admin", ((SysUser) principal).getUsername())) {
hasPermission = true;
} else {
//讀取用戶所擁有權限所有的URL 在這裏全部返回true
Set<String> urls = new HashSet<>();
for (String url : urls) {
if (antPathMatcher.match(url, request.getRequestURI())) {
hasPermission = true;
break;
}
}
}
}
return hasPermission;
}
public boolean checkUserId(Authentication authentication, int id) {
return true;
}
}
Method安全表達式
針對方法級別的訪問控制比較複雜,spring security
提供了4種註解分別是 @PreAuthorize
,
@PreFilter
,@PostAuthorize
,@PostFilter
使用method註解
開啓方法級別的註解配置
在security配置類中添加註解
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConf extends WebSecurityConfigurerAdapter {
其他配置忽略。。。可查看上一篇文章
在方法上使用註解
/**
* 查詢所有人員
*/
@PreAuthorize("hasRole('ADMIN')")
@GetMapping(value = "/users")
public List<User> getUsers() {
return userService.findAll();
}
PreAuthorize
@ProAuthorize 註解適合進入方法錢的權限驗證
@PreAuthorize("hasRole('ADMIN')")
list<User> findAll();
PostAuthorize
@PostAuthorize在方法執行後再進行權限驗證,適合驗證帶有返回值的權限,Spring EL
提供返回對象能夠在表達式語言中獲取到返回對象的 returnObject
@PostAUthorize("returnObject.username == authentication.username")
User findOne(long id);
PreAuthorize針對參數進行過濾
//當有多個對象時使用filterTarget進行標柱
@PreFilter(filterTarget = "ids",value = "filterObject % 2 == 0")
void delete(List<Long> ids);
PostFilter 針對返回結果進行過濾
@PreAuthorize("hasAuthority('user:list')")
@PostFilter("filterObject.username == authentication.username")
List<User> findAll();
源碼
github地址:https://github.com/jamesluozhiwei/security
如果對您有幫助請高擡貴手點個star
關注公衆號獲取更多諮詢