首页 > 其他分享 >Spring Security的四种权限控制方式

Spring Security的四种权限控制方式

时间:2023-04-25 13:22:20浏览次数:30  
标签:控制 users Spring Security 权限 public

关注我了解更多Java技术知识,带你一路“狂飙”到底!上岸大厂不是梦!

在前面的章节中,已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是认证+授权。下面班分享:Spring教程之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 接口,在该接口中定义了一系列的方法,用于用户权限的设置,如下图:

SecurityExpressionOperations接口中的

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

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

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

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 List getAllUser() {
List users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User(i, "yyg-" + i));
}
return users;
}
}

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

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 List doFilter(List ids, List users) {
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 List getAllUser() {
List users = 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 List getUserInfos() {
List ids = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ids.add(i);
}
List users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add(new User(i, "yyg-" + i));
}
return filterService.doFilter(ids, users);
}
}

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

4. 代码结构

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

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

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

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

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

标签:控制,users,Spring,Security,权限,public
From: https://www.cnblogs.com/qian-fen/p/17352308.html

相关文章

  • SpringBoot 日志切面
    SpringBoot日志切面在SpringBoot中搞一下AOP切面,复习一下。太详细的概念就不用说了,直接看SpringAOP实现吧,当时写的除了有点模糊也没什么大问题。AOP概念在SpringBoot中使用AOP,直接引入spring-boot-starter-aop的包即可:<dependency><groupI......
  • SpringContextUtils
    importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.NoSuchBeanDefinitionException;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;importorg.springfr......
  • spring IoC和DI
    IoC控制反转IoC是InversionofControl的缩写。他是一种软件设计原则,用于减少代码之间的耦合度。在IoC中,对象不在负责管理和创建他们依赖的对象,而是将这些任务交给外部容器,来完成。这样做可以使代码更加松散耦合,更容易扩展和维护。控制反转的主要思想是将对象的创建和管理交给Io......
  • SpringSecurity从入门到精通:认证配置详解&权限系统的作用
    认证配置详解Configpackagecom.sangeng.config;importcom.sangeng.filter.JwtAuthenticationTokenFilter;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.ann......
  • Spring Boot Configuration Annotation Processor not configured
    一、Springboot自定义配置实现自动提示@ConfigurationProperties的作用:让JavaBean中属性值要和配置文件进行映射@Getter@Setter@ConfigurationProperties(prefix="jwt")publicclassJwtProperties{/***JWT加解密使用的密钥*/privateString......
  • spring boot 切片测试
    我想问大家一下使用springboot项目的时候做单元测试的时,使用的哪种方式?有很多小伙伴使用spring-boot-starter-test,但是这种测试是比较笨重的。当你想要测一个方法时,相关于把整个springboot项目启动启动测试这一个方法如果项目使用的组件很多,比如有redis,数据库,kafka,minio等......
  • SpringBoot监控Actuator,关闭redis监测
    当我们导入了spring-boot-starter-actuator这个依赖后,SpringBoot会默认去监测一些信息。其中就包括redis、会根据redis的默认初始配置,localhost:6379尝试连接redis。如果我们没有用到redis,启动就会报错<dependency><groupId>org.springframework.boot</groupId>......
  • Xxl-job安装部署以及SpringBoot集成Xxl-job使用
    1、安装Xxl-job:可以使用docker拉取镜像部署和源码编译两种方式,这里选择源码编译安装。代码拉取地址:https://github.com/xuxueli/xxl-job/tree/2.1.2官方开发文档:https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA......
  • java面试题--Spring
    一、Spring、SpringMVC、SpringBoot的区别是什么?二、????三、SpringMVC工作流程是什么?1、DispatcherServlet接收请求,将请求发给HandlerMapping;2、HandlerMapping根据请求url,匹配到要处理的handler,并包装成处理器执行链,返回给DispatcherServlet。3、DispatcherServlet根据处理器......
  • SpringBoot接口支持配置https步骤
    本地利用JDK工具生成证书1.keytool-genkey-keyalgRSA-keystoretomcat.jks2.keytool-importkeystore-srckeystoretomcat.jks-destkeystoretomcat.pkcs12-deststoretypepkcs12 验证是否成功keytool-list-vkeystoretomcat.jks keytool-list-vkeystoretom......