本文主要是介绍Spring Security 基于表达式的权限控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
spring security 3.0
已经可以使用spring el
表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。
常见的表达式
Spring Security可用表达式对象的基类是SecurityExpressionRoot。
表达式 | 描述 |
---|---|
hasRole([role] ) | 用户拥有制定的角色时返回true (Spring security 默认会带有ROLE_ 前缀),去除参考Remove the ROLE_ |
hasAnyRole([role1,role2]) | 用户拥有任意一个制定的角色时返回true |
hasAuthority([authority]) | 等同于hasRole ,但不会带有ROLE_ 前缀 |
hasAnyAuthority([auth1,auth2]) | 等同于hasAnyRole |
permitAll | 永远返回true |
denyAll | 永远返回false |
anonymous | 当前用户是anonymous 时返回true |
rememberMe | 当前勇士是rememberMe 用户返回true |
authentication | 当前登录用户的authentication 对象 |
fullAuthenticated | 当前用户既不是anonymous 也不是rememberMe 用户时返回true |
hasIpAddress('192.168.1.0/24')) | 请求发送的IP匹配时返回true |
部分代码:
......
private String defaultRolePrefix = "ROLE_"; //ROLE_前缀/** Allows "permitAll" expression */public final boolean permitAll = true; //全部true/** Allows "denyAll" expression */public final boolean denyAll = false; //全部false
public final boolean permitAll() {return true;}public final boolean denyAll() {return false;}public final boolean isAnonymous() {//是否是anonymousreturn trustResolver.isAnonymous(authentication);}public final boolean isRememberMe() {//是否是remembermereturn trustResolver.isRememberMe(authentication);}
......
URL安全表达式
onfig.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')").anyRequest().authenticated();
这里我们定义了应用/person/*
URL的范围,该URL只针对拥有ADMIN
或者USER
权限的用户有效。
在Web安全表达式中引用bean
config.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')").antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)").anyRequest().access("@rbacService.hasPermission(request,authentication)");
RbacServiceImpl
@Component("rbacService")
@Slf4j
public class RbacServiceImpl implements RbacService {/*** uri匹配工具*/private AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic boolean hasPermission(HttpServletRequest request, Authentication authentication) {log.info("【RbacServiceImpl】 --hasPermission={}", authentication.getPrincipal());Object principal = authentication.getPrincipal();boolean hasPermission = false;//有可能是匿名的anonymousif (principal instanceof SysUser) {//admin永远放回trueif (StringUtils.equals("admin", ((SysUser) principal).getUsername())) {hasPermission = true;} else {//读取用户所拥有权限所有的URL 在这里全部返回trueSet<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
提供了四种注解,分别是@PreAuthorize
, @PreFilter
, @PostAuthorize
和 @PostFilter
使用method注解
- 开启方法级别注解的配置
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class MerryyouSecurityConfig extends WebSecurityConfigurerAdapter {
- 配置相应的bean
@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Bean@ConditionalOnMissingBean(PasswordEncoder.class)public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
- 在方法上面使用注解
/** * 查询所有人员 */ @PreAuthorize(“hasRole(‘ADMIN’)”) @ApiOperation(value = “获得person列表”, notes = “”) @GetMapping(value = “/persons”) public List getPersons() { return personService.findAll(); }
PreAuthorize
@PreAuthorize 注解适合进入方法前的权限验证
@PreAuthorize("hasRole('ADMIN')")List<Person> findAll();
PostAuthorize
@PostAuthorize 在方法执行后再进行权限验证,适合验证带有返回值的权限。Spring EL
提供 返回对象能够在表达式语言中获取返回的对象return Object
。
@PostAuthorize("returnObject.name == authentication.name")Person findOne(Integer id);
PreFilter 针对参数进行过滤
//当有多个对象是使用filterTarget进行标注
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {...}
PostFilter 针对返回结果进行过滤
@PreAuthorize("hasRole('ADMIN')")@PostFilter("filterObject.name == authentication.name")List<Person> findAll();
效果如下:
这篇关于Spring Security 基于表达式的权限控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!