在上一篇文章已经介绍了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
}
http.antMatchers("/test/*").access("hasRole('ADMIN') or hasRole('USER')")
.anyRequest().authenticated();
这里我们定义了 /test/
URL的范围,只有拥有 ADMIN
或 USER
权限的用户可以访问 /test/
匹配的URL
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;
}
}
针对方法级别的访问控制比较复杂,spring security
提供了4种注解分别是 @PreAuthorize
,
@PreFilter
,@PostAuthorize
,@PostFilter
在security配置类中添加注解
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConf extends WebSecurityConfigurerAdapter {
其他配置忽略。。。可查看上一篇文章
/**
* 查询所有人员
*/
@PreAuthorize("hasRole('ADMIN')")
@GetMapping(value = "/users")
public List<User> getUsers() {
return userService.findAll();
}
@ProAuthorize 注解适合进入方法钱的权限验证
@PreAuthorize("hasRole('ADMIN')")
list<User> findAll();
@PostAuthorize在方法执行后再进行权限验证,适合验证带有返回值的权限,Spring EL
提供返回对象能够在表达式语言中获取到返回对象的 returnObject
@PostAUthorize("returnObject.username == authentication.username")
User findOne(long id);
//当有多个对象时使用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
个人博客:https://www.cqwxhn.xin
关注公众号获取更多咨询