博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security 基于表达式的权限控制
阅读量:7067 次
发布时间:2019-06-28

本文共 4479 字,大约阅读时间需要 14 分钟。

hot3.png

前言

spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。

常见的表达式

Spring Security可用表达式对象的基类是SecurityExpressionRoot。

表达式 描述
hasRole([role]) 用户拥有制定的角色时返回true (Spring security默认会带有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; //全部falsepublic final boolean permitAll() {		return true;	}	public final boolean denyAll() {		return false;	}	public final boolean isAnonymous() {		//是否是anonymous		return trustResolver.isAnonymous(authentication);	}	public final boolean isRememberMe() {		//是否是rememberme		return 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")@Slf4jpublic class RbacServiceImpl implements RbacService {    /**     * uri匹配工具     */    private AntPathMatcher antPathMatcher = new AntPathMatcher();    @Override    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {        log.info("【RbacServiceImpl】  --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
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注解

  1. 开启方法级别注解的配置
    @Configuration@EnableGlobalMethodSecurity(prePostEnabled = true)public class MerryyouSecurityConfig extends WebSecurityConfigurerAdapter {
  2. 配置相应的bean
    @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception {     return super.authenticationManagerBean(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception {     auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean @ConditionalOnMissingBean(PasswordEncoder.class) public PasswordEncoder passwordEncoder(){     return new BCryptPasswordEncoder(); }
  3. 在方法上面使用注解
    /*** 查询所有人员 */ @PreAuthorize(“hasRole(‘ADMIN’)”) @ApiOperation(value = “获得person列表”, notes = “”) @GetMapping(value = “/persons”) public List getPersons() {     return personService.findAll(); }

PreAuthorize

@PreAuthorize 注解适合进入方法前的权限验证

@PreAuthorize("hasRole('ADMIN')")    List
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
ids, List
usernames) { ...}

PostFilter 针对返回结果进行过滤

@PreAuthorize("hasRole('ADMIN')") @PostFilter("filterObject.name == authentication.name") List
findAll();

效果如下:

转载于:https://my.oschina.net/liuyuantao/blog/1924776

你可能感兴趣的文章
【探索】VS下虚继承实现的方法-1
查看>>
Java基础加密之MD5加密算法
查看>>
盛夏光年
查看>>
Android 沉浸式状态栏(像IOS那样的状态栏与应用统一颜色样式)
查看>>
指针、动态分配与链表
查看>>
RHCS集群服务 7.10
查看>>
windows 使用vnc图形化界面远程连接阿里云ubuntu 16.04云服务器
查看>>
linux和CentOS是什么关系;CentOS和RHEL是什么关系
查看>>
samba
查看>>
myeclipse+maven搭建web项目方法一(超级详细)
查看>>
利用Python网络爬虫抓取微信好友的签名及其可视化展示
查看>>
Linux-Nginx代理
查看>>
计算机的系统组成简介---运维笔记
查看>>
Liunx nginx 的使用方法及模块
查看>>
美国邮政署网站的一个高危漏洞暴露了6000万用户的数据
查看>>
人脸识别解锁能用照片绕过?华为、三星、小米、HTC等均上榜
查看>>
SQL SERVER得到一个月所有的日期
查看>>
子网线划分+综合布线
查看>>
rsync远程同步
查看>>
袋鼠云数据中台专栏(一) :浅析数据中台策略与建设实践
查看>>