Version: Next
权限表达式
.access()
方法
- 所有可填表达式内容:
表达式函数 | 描述 |
---|---|
hasRole([role] ) | 用户拥有指定的角色时返回true (Spring security 默认会带有ROLE_ 前缀),去除前缀参考Remove the ROLE_ |
hasAnyRole([role1,role2]) | 用户拥有任意一个指定的角色时返回true |
hasAuthority([authority]) | 拥有某资源的访问权限时返回true |
hasAnyAuthority([auth1,auth2]) | 拥有某些资源其中部分资源的访问权限时返回true |
permitAll | 永远返回true |
denyAll | 永远返回false |
anonymous | 当前用户是anonymous 时返回true |
rememberMe | 当前用户是rememberMe 用户返回true |
authentication | 当前登录用户的authentication 对象 |
fullAuthenticated | 当前用户既不是anonymous 也不是rememberMe 用户时返回true |
hasIpAddress('192.168.1.0/24') | 请求发送的IP匹配时返回true |
全局级别表达式
URL表达式
config.antMatchers("/system/*").access("hasAuthority('ADMIN') or hasAuthority('USER')")
.anyRequest().authenticated();
将Bean填入表达式
@Component("rbacService")
@Slf4j
public class RbacService {
//返回true表示验证通过
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
//验证逻辑代码
return true;
}
public boolean checkUserId(Authentication authentication, int id) {
//验证逻辑代码
return true;
}
}
- 处理RESTFul风格的路径参数
- 与Controller一样,用
{}
框住 - 用
#
取
- 与Controller一样,用
config.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication, #id)")
.anyRequest().access("@rbacService.hasPermission(request, authentication)");
方法级别表达式
针对某一个方法
@PreAuthorize
@PreFilter
@PostAuthorize
@PostFilter
Pre:前置; Post:后置
Authorize:对方法访问的权限
Filter:对参数和返回值的过滤
@PreAuthorize
@PreAuthorize
注解适合进入方法前的权限验证。只有拥有ADMIN角色才能访问findAll方法
@PreAuthorize("hasRole('admin')")
public List<PersonDemo> findAll(){
return null;
}
如果当前登录用户没有PreAuthorize
需要的权限,将抛出org.springframework.security.access.AccessDeniedException
异常!
@PostAuthorize
@PostAuthorize
在方法执行后再进行权限验证,适合根据返回值结果进行权限验证。Spring EL
提供返回对象能够在表达式语言中获取返回的对象returnObject
。下文代码只有返回值的name等于authentication对象的name(当前登录用户名)才能正确返回,否则抛出异常。
@PostAuthorize("returnObject.name == authentication.name")
public PersonDemo findOne(){
String authName =
SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println(authName);
return new PersonDemo("admin");
}
@PreFilter
PreFilter 针对参数进行过滤,下文代码表示针对ids参数进行过滤,只有id为偶数的元素才被作为参数传入函数
//当有多个对象是使用filterTarget进行标注
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
}
@PostFilter
PostFilter 针对返回结果进行过滤,特别适用于集合类返回值,过滤集合中不符合表达式的对象
@PostFilter("filterObject.name == authentication.name")
public List<PersonDemo> findAllPD(){
List<PersonDemo> list = new ArrayList<>();
list.add(new PersonDemo("kobe"));
list.add(new PersonDemo("admin"));
return list;
}
如果使用admin登录系统,上面的函数返回值list中kobe将被过滤掉,只剩下admin
开启:
- 需要在Spring Security配置类上添加
@EnableGlobalMethodSecurity(prePostEnabled = true)
注解
Pojo: PersonDemo
public class PersonDemo {
private String name;
public PersonDemo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- MethodELService
@Service
public class MethodELService {
@PreAuthorize("hasRole('admin')")
public List<PersonDemo> findAll() {
return null;
}
@PostAuthorize("returnObject.name == authentication.name")
public PersonDemo findOne() {
String authName =
SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println(authName);
return new PersonDemo("admin");
}
@PreFilter(filterTarget = "ids", value = "filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
System.out.println();
}
@PostFilter("filterObject.name == authentication.name")
public List<PersonDemo> findAllPD() {
List<PersonDemo> list = new ArrayList<>();
list.add(new PersonDemo("kobe"));
list.add(new PersonDemo("admin"));
return list;
}
}
- Controller
@Controller
public class BizpageController {
@Resource
MethodELService methodELDemo;
// 具体业务一
@GetMapping("/biz1")
public String updateOrder() {
//methodELDemo.findAll();
//methodELDemo.findOne();
/*List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
methodELDemo.delete(ids,null);*/
List<PersonDemo> pds = methodELDemo.findAllPD();
return "biz1";
}
}