深入浅出spring原理及实战「开发实战系列」springsecurity技术实战之通过注解表达式控制方法权限(代码片段)

洛神灬殇 洛神灬殇     2023-03-27     397

关键词:

Spring Security权限控制机制

Spring Security中可以通过表达式控制方法权限,其中有四个支持使用表达式的注解,分别是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前两者可以用来在方法调用前或者调用后进行权限检查,后两者可以用来对集合类型的参数或者返回值进行过滤。

启动Security机制的配置

它们的定义能够对我们的方法的调用产生影响我们需要设置global-method-security元素的pre-post-annotations=”enabled”,默认为disabled。

xml配置方式

<security:global-method-security pre-post-annotations="disabled"/>

JavaConfig配置方式

类上增加@EnableGlobalMethodSecurity(securedEnabled = true)注解,secureEnabled默认为false,使其赋值为true才能使用相关注解。

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)
public class XXXApplication 
    public static void main(String[] args) 
        SpringApplication.run(XXXApplication.class, args);
    


@PreAuthorize和@PostAuthorize进行访问控制

@PreAuthorize 注解,顾名思义是进入方法前的权限验证,@PreAuthorize 声明这个方法所需要的权限表达式,例如:@PreAuthorize(“hasAuthority(‘sys:dept:delete’)”),@PreAuthorize 表示访问方法或类在执行之前先判断权限,一般都是使用这个注解,注解的参数和access()方法参数取值相同,都是权限表达式。若有多个权限,可用逗号隔开。

根据这个注解所需要的权限,再和当前登录的用户角色所拥有的权限对比,如果用户的角色权限集Set中有这个权限,则放行;没有,拒绝

@GetMapping("/query")
//以下几个注解都表示ADMIN用户具有访问"/query"接口的权限
@PreAuthorize("hasAnyRole('ADMIN')")
@Secured("ROLE_ADMIN")//以ROLE_开头,不能缺少
@PostAuthorize("hasAnyRole('ADMIN')")
 public String query()
        return "querySuccess";
 

定义相关的接口上

public interface UserService 
    public boolean ifhaveuser(String username,String password);
    List<User> findAllUsers();
    User findById(int id);
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    void updateUser(User user);
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    void deleteUser(int id);

@Service
public class UserServiceImpl implements UserService undefined

   @PreAuthorize("hasRole('ROLE_ADMIN')")
   public void addUser(User user) undefined
      System.out.println("addUser................" + user);
   

   @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
   public User find(int id) undefined
      System.out.println("find user by id............." + id);
      return null;
   

在上面的代码中我们定义了只有拥有角色ROLE_ADMIN的用户才能访问adduser()方法,而访问find()方法需要有ROLE_USER角色或ROLE_ADMIN角色。使用表达式时我们还可以在表达式中使用方法参数。

PreAuthorize的EL表达式

public class UserServiceImpl implements UserService undefined
   /**
    * 限制只能查询Id小于10的用户
   */
   @PreAuthorize("#id<10")
   public User find(int id) undefined
      System.out.println("find user by id........." + id);
      return null;
   

   /**
    * 限制只能查询自己的信息
    */
   @PreAuthorize("principal.username.equals(#username)")
   public User find(String username) undefined
      System.out.println("find user by username......" + username);
      return null;
   

   /**
    * 限制只能新增用户名称为abc的用户
    */
   @PreAuthorize("#user.name.equals('abc')")
   public void add(User user) undefined
      System.out.println("addUser............" + user);
   

在上面代码中我们定义了调用find(int id)方法时,只允许参数id小于10的调用;调用find(String username)时只允许username为当前用户的用户名;定义了调用add()方法时只有当参数user的name为abc时才可以调用。

  • @Secured使用时必须要加上ROLE_前缀,不可省略。@PreAuthorize 也可加上ROLE_前缀,不过其可以省略。

用户的角色权限Set,是什么时候存入的,其流程如下

PostAuthorize的EL表达式

  • @PostAuthorize表示方法或类执行结束后判断权限,很少使用。

有时候可能你会想在方法调用完之后进行权限检查,这种情况比较少,但是如果你有的话,Spring Security也为我们提供了支持,通过@PostAuthorize可以达到这一效果。使用@PostAuthorize时我们可以使用内置的表达式returnObject表示方法的返回值。

下面这一段示例代码:

@PostAuthorize("returnObject.id%2==0")
   public User find(int id) undefined
      User user = new User();
      user.setId(id);
      return user;

上面这一段代码表示将在方法find()调用完成后进行权限检查,如果返回值的id是偶数则表示校验通过,否则表示校验失败,将抛出AccessDeniedException。

注意的是@PostAuthorize是在方法调用完成后进行权限检查,它不能控制方法是否能被调用,只能在方法调用完成后检查权限决定是否要抛出AccessDeniedException。

@PreFilter和@PostFilter进行过滤

使用@PreFilter和@PostFilter可以对集合类型的参数或返回值进行过滤。使用@PreFilter和@PostFilter时,Spring Security将移除使对应表达式的结果为false的元素。

 @PostFilter("filterObject.id%2==0"public List<User> findAll() undefined
      List<User> userList = new ArrayList<User>();
      User user;
      for (int i=0; i<10; i++) undefined
         user = new User();
         user.setId(i);
         userList.add(user);
      
      return userList;
   

上述代码表示将对返回结果中id不为偶数的user进行移除。filterObject是使用@PreFilter和@PostFilter时的一个内置表达式,表示集合中的当前对象。当@PreFilter标注的方法拥有多个集合类型的参数时,需要通过@PreFilter的filterTarget属性指定当前@PreFilter是针对哪个参数进行过滤的。

参考资料

https://www.jianshu.com/p/3ddd2b31cb86

深入浅出spring原理及实战「开发实战系列」手把手教你将@schedule任务调度升级为分布式调度@distributeschedule(代码片段)

背景介绍很多小伙伴们都跟我留言说过一个类似的问题,就是针对于任务调度框架而言的选取,很多公司都会采用任务调度框架的鼻祖Quartz,那么我们来梳理以下Java领域的任务调度框架吧。Java领域的定时任务的框架... 查看详情

深入浅出spring原理及实战「开发实战系列」springsecurity技术实战之通过注解表达式控制方法权限(代码片段)

SpringSecurity权限控制机制SpringSecurity中可以通过表达式控制方法权限,其中有四个支持使用表达式的注解,分别是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前两者可以用来在方法调用前或者调用后进行... 查看详情

深入浅出spring原理及实战「开发实战系列」采用protostuff和kryo高性能序列化框架实现redistemplate的序列化组件(代码片段)

序列化序列化可以简单理解为对象–>字节的过程,同理,反序列化则是相反的过程。为什么需要序列化?因为网络传输只认字节。所以互信的过程依赖于序列化。网络传输的性能等诸多因素,通常会支持多种序... 查看详情

深入浅出spring原理及实战「开发实战系列」oauth2的技术体系架构和开发概览

背景介绍主要实现OAuth2的三种授权模式:密码模式、客户端模式和授权码模式,包括展示授权服务器、资源服务器、客户端等几种角色的交互,以及JWT的整合。并且每个实例都提供两个代码版本:一个是基于旧的S... 查看详情

深入浅出spring原理及实战「开发实战系列」springsecurity与jwt实现权限管控以及登录认证指南(代码片段)

SpringSecurity介绍SpringSecurity是一个用于Java企业级应用程序的安全框架,主要包含用户认证和用户授权两个方面,相比较Shiro而言,Security功能更加的强大,它可以很容易地扩展以满足更多安全控制方面的需求,... 查看详情

深入浅出springcloud原理及实战「springcloud-alibaba系列」微服务模式搭建系统基础架构实战指南及版本规划踩坑分析

前提介绍SpringCloud-Alibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过SpringCloud编程模型轻松使用这些组件来开发分布式应用服务。依托SpringCloudAlibaba,您只需要... 查看详情

深入浅出spring原理及实战「源码原理实战」从底层角度去分析研究propertysourcesplaceholderconfigurer的原理及实战注入机制

Spring提供配置解析功能主要有一下xml文件占位符解析和Java的属性@Value的占位符解析配置这两种场景进行分析和实现解析,如下面两种案例。xml文件的占位符解析配置<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"init-method="i... 查看详情

深入浅出dubbo3原理及实战「技术大纲」深入浅出并发实战课程系列及技术指南

Dubbo3开题简介如开篇所述,Dubbo提供了构建云原生微服务业务的一站式解决方案,可以使用Dubbo快速定义并发布微服务组件,同时基于Dubbo开箱即用的丰富特性及超强的扩展能力,构建运维整个微服务体系所需的各... 查看详情

深入浅出sentinel原理及实战「基础实战专题」零基础实现服务流量控制实战开发指南

你若要喜爱你自己的价值,你就得给世界创造价值。Sentinel的组成部分Sentinel主要由以下两个部分组成。Sentinel核心库(Java客户端):Sentinel的核心库不依赖任何框架或库,能够运行于Java8及以上的版本的运行时环境中,同时对Spri... 查看详情

深入浅出sentinel原理及实战「基础实战专题」零基础探索分析sentinel控制台开发指南

Sentinel控制台Sentinel提供了一个轻量级的开源控制台SentinelDashboard,它提供了机器发现与健康情况管理、监控(单机和集群)、规则管理与推送等多种功能。Sentinel控制台提供的功能如下查看机器列表以及健康情况:Sentnel控制台能... 查看详情

深入浅出spring原理及实战「原理分析专题」从零开始教你springel表达式使用和功能分析讲解指南(上篇)(代码片段)

SpringEL表达式语言,这种语言jsp中学到的el,但是在整个spring之中其表达式语言要更加的复杂,而且支持度更加的广泛,最重要的是他可以进行方法的调用,对象的实例化,集合操作等等,但是唯一的难点就是:代码太复杂了,表达式太复杂... 查看详情

精华推荐|深入浅出rocketmq原理及实战「底层源码挖掘系列」透彻剖析贯穿rocketmq的消费者端的运行核心的流程(上篇)

精华推荐|【深入浅出RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿RocketMQ的消费者端的运行核心的流程上篇:分析对应总体消费流程的判断和校验以及限流控制和回调等处理流程分析下篇:分析基于上篇的总体流程的... 查看详情

深入浅出springcloud原理及实战「netflix系列之hystrix」针对于限流熔断组件hystrix的基本参数和实现原理介绍分析(代码片段)

...此度过糟糕的一生。[温馨提示]承接第一篇文章🏹【深入浅出SpringCloud原理及实战】「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的基本参数和实现原理介绍分析在这里推荐给大家martinfowler的熔断器介绍和权威指南,有兴趣... 查看详情

深入浅出springcloud原理及实战「netflix系列之hystrix」针对于限流熔断组件hystrix的超时机制的原理和实现分析(代码片段)

...此度过糟糕的一生。[温馨提示]承接第一篇文章🏹【深入浅出SpringCloud原理及实战】「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的基本参数和实现原理介绍分析在这里推荐给大家martinfowler的熔断器介绍和权威指南,有兴趣... 查看详情

深入浅出seata原理及实战「入门基础专题」探索seata服务的at模式下的分布式开发实战指南

承接上文上一篇文章说到了Seata为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。那么接下来我们将要针对于AT模式下进行分布式事务开发的原理进行介绍以及实战。SeataAT模式在AT、TCC、SAGA和XA这四种... 查看详情

精华推荐|深入浅出rocketmq原理及实战「底层原理挖掘系列」透彻剖析贯穿rocketmq的存储系统的实现原理和持久化机制

RocketMQ的发展历史RocketMQ是一个统一消息引擎、轻量级数据处理平台。RocketMQ是一款阿里巴巴开源的消息中间件。2016年11月28日,阿里巴巴向广西党性培训Apache软件基金会捐赠RocketMQ,成为Apache孵化项目。2017年9月25日,Apache宣布Rock... 查看详情

精华推荐|深入浅出rocketmq原理及实战「底层原理挖掘系列」透彻剖析贯穿rocketmq的存储系统的实现原理和持久化机制

RocketMQ的发展历史RocketMQ是一个统一消息引擎、轻量级数据处理平台。RocketMQ是一款阿里巴巴开源的消息中间件。2016年11月28日,阿里巴巴向广西党性培训Apache软件基金会捐赠RocketMQ,成为Apache孵化项目。2017年9月25日,A... 查看详情

深入浅出spring原理及实战「源码调试分析」结合datasourceregister深入分析importbeandefinitionregistrar的源码运作流程

每日一句人的一生中不可能会一帆风顺,总会遇到一些挫折,当你对生活失去了信心的时候,仔细的看一看、好好回想一下你所遇到的最美好的事情吧,那会让你感觉到生活的美好。注入案例代码如何通过实现SpringBoot框架带有... 查看详情