千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > 爆破专栏丨Spring Security系列教程之Spring Security的四种权限控制方式

爆破专栏丨Spring Security系列教程之Spring Security的四种权限控制方式

来源:千锋教育
发布人:qyf
时间: 2021-10-27 16:46:00 1635324360

  原创:一一哥

  前言:

  在前面的章节中,一一哥 已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是认证+授权。

  在前面我们分别基于内存模型、基于默认的数据库模型、基于自定义数据库模型实现了认证和授权功能,但是不管哪种方式,我们对某个接口的拦截限制,都是通过编写一个SecurityConfig配置类,在该类的configure (Http Security http)方法中,通过http. authorize Requests ( ). antMatchers ("/admin/**")...这样的代码进行的权限控制。

  这种权限控制方法虽然也可以实现对某些接口的拦截或放行,但是不够灵活,其实Spring Security对接口的拦截或放行的写法,还有另外的方式,接下来请跟我学习一下吧!

  一. 权限控制方式

  在Spring Security 中,我们既可以使用 Spring Security 提供的默认方式进行授权,也可以进行自定义授权,总之在Spring Security中权限控制的实现方式是比较灵活多样的。在Spring Security 中,对接口的拦截或放行,有四种常见的权限控制方式:

  利用Ant表达式实现权限控制;

  利用授权注解结合SpEl表达式实现权限控制;

  利用过滤器注解实现权限控制;

  利用动态权限实现权限控制。

  对上面说到的四种权限控制方式,我们接下来分别进行讲解实现。

  二. 利用Ant表达式实现权限控制

  利用Ant表达式的权限控制方式,是我们之前一直在使用的权限控制方式,在进行代码实现之前,我先对这种方式的底层实现进行简单分析。

  1. Spring Security中的权限控制方法

  在Spring Security中,有一个Security Expression Operations 接口,在该接口中定义了一系列的方法,用于用户权限的设置,如下图:

1.webp

  SecurityExpressionOperations接口中的

  这些方法作用如下图所示:

2.webp

3.webp

  2. Spring Security中的权限控制粒度

  这个接口有一个SecurityExpressionRoot子类,该类提供了基于表达式的权限控制实现方式。而这个SecurityExpressionRoot 又有两个实现子类,分别用于实现 URL Web接口粒度的权限控制和方法粒度的权限控制,如下图所示:

4.webp

  3. 代码实现

  从上面的小节中,我们知道在Spring Security中,支持2种粒度的权限控制,即URL Web接口粒度 和方法粒度,而我们这里所谓的 Ant表达式授权控制方式,就是通过Ant表达式来控制 URL 接口的访问权限。

  那么如果我们需要对URL接口粒度进行权限控制,按如下代码即可实现:

  @Override

  protected void configure(HttpSecurity http) throws Exception {

  http.authorizeRequests()

  .antMatchers("/admin/**")

  .hasRole("ADMIN")

  .antMatchers("/user/**")

  .hasRole("USER")

  .antMatchers("/visitor/**")

  .permitAll()

  .anyRequest()

  .authenticated()

  .and()

  .formLogin()

  .permitAll()

  .and()

  //对跨域请求伪造进行防护---->csrf:利用用户带有登录状态的cookie进行攻击的手段

  .csrf()

  .disable();

  }

  以上代码中,/admin/ 格式的路径需要 admin 角色才可以访问,/user/ 格式的路径需要 user 角色才可以访问,/visitor/** 格式的路径可以直接访问,其他接口路径则需要登录后才能访问。

  三. 利用授权注解结合SpEl表达式实现权限控制

  1. 授权注解

  除了可以使用上面的Ant表达式进行授权实现,我们也可以在方法上添加授权注解来权限控制,常用的授权注解有3个:

  @PreAuthorize:方法执行前进行权限检查;

  @PostAuthorize:方法执行后进行权限检查;

  @Secured:类似于 @PreAuthorize。

  2. 代码实现

  要想利用以上3个授权注解进行权限控制,我们首先需要利用@EnableGlobalMethodSecurity注解开启授权注解功能,代码如下:

  @Configuration

  @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)

  public class SecurityConfig extends WebSecurityConfigurerAdapter {

  ...

  ...

  }

  然后在具体的接口方法上利用授权注解进行权限控制,代码如下:

  @RestController

  public class UserController {

  @Secured({"ROLE_USER"})

  //@PreAuthorize("principal.username.equals('user')")

  @GetMapping("/user/hello")

  public String helloUser() {

  return "hello, user";

  }

  @PreAuthorize("hasRole('ADMIN')")

  @GetMapping("/admin/hello")

  public String helloAdmin() {

  return "hello, admin";

  }

  @PreAuthorize("#age>100")

  @GetMapping("/age")

  public String getAge(@RequestParam("age") Integer age) {

  return String.valueOf(age);

  }

  @GetMapping("/visitor/hello")

  public String helloVisitor() {

  return "hello, visitor";

  }

  }

  可以看出,这种写法明显比利用Ant表达式进行权限控制更灵活方便,所以开发时这种写法很常用。

  四. 利用过滤器注解实现权限控制

  1. 过滤器注解简介

  在Spring Security中还提供了另外的两个注解,即@PreFilter和@PostFilter,这两个注解可以对集合类型的参数或返回值进行过滤。使用@PreFilter和@PostFilter时,Spring Security将移除对应表达式结果为false的元素。

  2. @PostFilter的用法

  @PostFilter注解主要是用于对集合类型的返回值进行过滤,filterObject是@PostFilter中的一个内置表达式,表示集合中的元素对象。

  @Slf4j

  @RestController

  public class FilterController {

  /**

  * 只返回结果中id为偶数的user元素。

  * filterObject是@PreFilter和@PostFilter中的一个内置表达式,表示集合中的当前对象。

  */

  @PostFilter("filterObject.id%2==0")

  @GetMapping("/users")

  public ListgetAllUser() {

  Listusers = new ArrayList<>();

  for (int i = 0; i < 10; i++) {

  users.add(new User(i, "yyg-" + i));

  }

  return users;

  }

  }

  我们启动浏览器进行测试,可以看到测试接口中只返回了id为偶数的元素。

5.webp

  3. @PreFilter的用法

  使用@PreFilter也可以对集合类型的参数进行过滤,当@PreFilter标注的方法内拥有多个集合类型的参数时,可以通过@PreFilter的filterTarget属性来指定当前是针对哪个参数进行过滤的;而filterObject是@PreFilter中的一个内置表达式,表示集合中的元素对象。

  为了方便测试,我们在Service层中进行过滤操作,然后在Controller层中进行调用。

  FilterService类中的方法定义:

  @Slf4j

  @Service

  public class FilterService {

  /**

  * 当@PreFilter标注的方法内拥有多个集合类型的参数时,

  * 可以通过@PreFilter的filterTarget属性来指定当前是针对哪个参数进行过滤的。

  */

  @PreFilter(filterTarget = "ids", value = "filterObject%2==0")

  public ListdoFilter(Listids, Listusers) {

  log.warn("ids=" + ids.toString());

  log.warn("users=" + users.toString());

  return ids;

  }

  }

  在Controller中定义一个测试接口:

  @Slf4j

  @RestController

  public class FilterController {

  /**

  * 只返回结果中id为偶数的user元素。

  * filterObject是@PreFilter和@PostFilter中的一个内置表达式,表示集合中的当前对象。

  */

  @PostFilter("filterObject.id%2==0")

  @GetMapping("/users")

  public ListgetAllUser() {

  Listusers = new ArrayList<>();

  for (int i = 0; i < 10; i++) {

  users.add(new User(i, "yyg-" + i));

  }

  return users;

  }

  @Autowired

  private FilterService filterService;

  @GetMapping("/users2")

  public ListgetUserInfos() {

  Listids = new ArrayList<>();

  for (int i = 0; i < 10; i++) {

  ids.add(i);

  }

  Listusers = new ArrayList<>();

  for (int i = 0; i < 10; i++) {

  users.add(new User(i, "yyg-" + i));

  }

  return filterService.doFilter(ids, users);

  }

  }

  我们启动浏览器进行测试,可以看到测试接口中只返回id为偶数的元素。

6.webp

  4. 代码结构

  下图是上面案例的代码结构,请参考实现:

7.webp

  五. 利用动态权限实现权限控制

  我们知道一个标准的RABC, 权限系统需要支持动态配置,Spring Security默认是在代码里约定好权限,真实的业务场景里通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色。

  而Spring Security中的动态权限,主要是通过重写拦截器和决策器来进行实现,最简单的方法就是自定义一个Filter去完成权限判断。其实这里涉及到的代码,基本和Spring Security关系不大,主要是在传统的Filter进行实现,我这里就不再进行描述了,感兴趣的同学可以自行实现!

  至此,我就给各位介绍了Spring Security中的4种进行权限控制的方式,各位可以结合自己的项目需求进行选择。

图片1

扫码关注公众号【Java架构栈】,获取全套专栏内容及代码

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT