Spring Security系列教程23--Spring Security的四种权限控制方式

简介: 前言在前面的章节中,一一哥 已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是 认证+授权。在前面我们分别基于内存模型、基于默认的数据库模型、基于自定义数据库模型实现了认证和授权功能,但是不管哪种方式,我们对某个接口的拦截限制,都是通过编写一个SecurityConfig配置类,在该类的configure(HttpSecurity http)方法中,通过http.authorizeRequests().antMatchers("/admin/**")...这样的代码进行的权限控制。这种权限控制方法虽然也可以实现对某些接口的拦截或放行,但

前言

在前面的章节中,一一哥 已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是 认证+授权。在前面我们分别基于内存模型、基于默认的数据库模型、基于自定义数据库模型实现了认证和授权功能,但是不管哪种方式,我们对某个接口的拦截限制,都是通过编写一个SecurityConfig配置类,在该类的configure(HttpSecurity http)方法中,通过http.authorizeRequests().antMatchers("/admin/**")...这样的代码进行的权限控制。

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

一. 权限控制方式

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

  • 利用Ant表达式实现权限控制;
  • 利用授权注解结合SpEl表达式实现权限控制;
  • 利用过滤器注解实现权限控制;
  • 利用动态权限实现权限控制。

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

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

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

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

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

SecurityExpressionOperations接口中的这些方法作用如下图所示:

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

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

3. 代码实现

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

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

@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
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)
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
    ...
    ...
}

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

@RestControllerpublicclassUserController {
@Secured({"ROLE_USER"})
//@PreAuthorize("principal.username.equals('user')")@GetMapping("/user/hello")
publicStringhelloUser() {
return"hello, user";
    }
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/hello")
publicStringhelloAdmin() {
return"hello, admin";
    }
@PreAuthorize("#age>100")
@GetMapping("/age")
publicStringgetAge(@RequestParam("age") Integerage) {
returnString.valueOf(age);
    }
@GetMapping("/visitor/hello")
publicStringhelloVisitor() {
return"hello, visitor";
    }
}

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

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

1. 过滤器注解简介

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

2. @PostFilter的用法

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

@Slf4j@RestControllerpublicclassFilterController {
/*** 只返回结果中id为偶数的user元素。* filterObject是@PreFilter和@PostFilter中的一个内置表达式,表示集合中的当前对象。*/@PostFilter("filterObject.id%2==0")
@GetMapping("/users")
publicList<User>getAllUser() {
List<User>users=newArrayList<>();
for (inti=0; i<10; i++) {
users.add(newUser(i, "yyg-"+i));
        }
returnusers;
    }
}

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

3. @PreFilter的用法

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

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

FilterService类中的方法定义:

@Slf4j@ServicepublicclassFilterService {
/*** 当@PreFilter标注的方法内拥有多个集合类型的参数时,* 可以通过@PreFilter的filterTarget属性来指定当前是针对哪个参数进行过滤的。*/@PreFilter(filterTarget="ids", value="filterObject%2==0")
publicList<Integer>doFilter(List<Integer>ids, List<User>users) {
log.warn("ids="+ids.toString());
log.warn("users="+users.toString());
returnids;
    }
}

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

@Slf4j@RestControllerpublicclassFilterController {
/*** 只返回结果中id为偶数的user元素。* filterObject是@PreFilter和@PostFilter中的一个内置表达式,表示集合中的当前对象。*/@PostFilter("filterObject.id%2==0")
@GetMapping("/users")
publicList<User>getAllUser() {
List<User>users=newArrayList<>();
for (inti=0; i<10; i++) {
users.add(newUser(i, "yyg-"+i));
        }
returnusers;
    }
@AutowiredprivateFilterServicefilterService;
@GetMapping("/users2")
publicList<Integer>getUserInfos() {
List<Integer>ids=newArrayList<>();
for (inti=0; i<10; i++) {
ids.add(i);
        }
List<User>users=newArrayList<>();
for (inti=0; i<10; i++) {
users.add(newUser(i, "yyg-"+i));
        }
returnfilterService.doFilter(ids, users);
    }
}

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

4. 代码结构

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

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

我们知道一个标准的RABC, 权限系统需要支持动态配置,Spring Security默认是在代码里约定好权限,真实的业务场景里通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色。而Spring Security中的动态权限,主要是通过重写拦截器和决策器来进行实现,最简单的方法就是自定义一个Filter去完成权限判断。其实这里涉及到的代码,基本和Spring Security关系不大,主要是在传统的Filter进行实现,我这里就不再进行描述了,感兴趣的同学可以自行实现!

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

相关文章
|
15天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
41 2
|
4月前
|
安全 Java 数据安全/隐私保护
使用Spring Security实现细粒度的权限控制
使用Spring Security实现细粒度的权限控制
|
4月前
|
安全 Java 数据库
实现基于Spring Security的权限管理系统
实现基于Spring Security的权限管理系统
|
4月前
|
安全 Java 数据安全/隐私保护
解析Spring Security中的权限控制策略
解析Spring Security中的权限控制策略
|
2月前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
Spring Retry 教程
|
1月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
详细介绍实现Java Spring Boot FCM推送教程
82 0
|
3月前
|
Java 数据库连接 Spring
一文讲明 Spring 的使用 【全网超详细教程】
这篇文章是一份全面的Spring框架使用教程,涵盖了从基础的项目搭建、IOC和AOP概念的介绍,到Spring的依赖注入、动态代理、事务处理等高级主题,并通过代码示例和配置文件展示了如何在实际项目中应用Spring框架的各种功能。
一文讲明 Spring 的使用 【全网超详细教程】
|
4月前
|
NoSQL Java 数据库连接
《滚雪球学Spring Boot》教程导航帖(更新于2024.07.16)
📚 《滚雪球学Spring Boot》是由CSDN博主bug菌创作的全面Spring Boot教程。作者是全栈开发专家,在多个技术社区如CSDN、掘金、InfoQ、51CTO等担任博客专家,并拥有超过20万的全网粉丝。该教程分为入门篇和进阶篇,每篇包含详细的教学步骤,涵盖Spring Boot的基础和高级主题。
65 1
《滚雪球学Spring Boot》教程导航帖(更新于2024.07.16)
|
3月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
147 0
|
3月前
|
Java 关系型数据库 MySQL