爆破专栏丨Spring Security系列教程之Spring Security的四种权限控制方式
原创:一一哥
前言:
在前面的章节中,一一哥 已经给大家介绍了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 ListgetAllUser() {
Listusers = 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 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为偶数的元素。
4. 代码结构
下图是上面案例的代码结构,请参考实现:
五. 利用动态权限实现权限控制
我们知道一个标准的RABC, 权限系统需要支持动态配置,Spring Security默认是在代码里约定好权限,真实的业务场景里通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色。
而Spring Security中的动态权限,主要是通过重写拦截器和决策器来进行实现,最简单的方法就是自定义一个Filter去完成权限判断。其实这里涉及到的代码,基本和Spring Security关系不大,主要是在传统的Filter进行实现,我这里就不再进行描述了,感兴趣的同学可以自行实现!
至此,我就给各位介绍了Spring Security中的4种进行权限控制的方式,各位可以结合自己的项目需求进行选择。
本文来自千锋教育,转载请注明出处。
爆破专栏丨Spring Security系列教程之Spring Security的四种权限控制方式相关推荐
- java按钮权限控制_详解Spring Security 中的四种权限控制方式
Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Se ...
- Spring Security系列教程之SpringSecurity密码加密和解密
创建一个springboot工程导入相应坐标 <dependency><groupId>org.springframework.security</groupId> ...
- JAVA常用框架系列教程之Spring(附视频)
大家好,框架作为程序员开发重要的学习部分,在java开发中,框架的学习也尤为的重要,框架不仅可以帮助大家高效的进行开发工作,更加能够优化工作步骤,从而提高开发人员的工作效率.为帮助Java编程的初学者 ...
- Security中常见的权限控制方式
本文来说下Security中常见的四种权限控制方式 文章目录 概述 概述
- java jdbc 教程_java JDBC系列教程之JDBC类的简析与JDBC的基础操作
什么是JDBC? 概念:JAVA Database Connectivity Javas数据库连接,Java语言操作数据库接口,然后由各个数据库厂商去实现这个接口,提供数据库驱动java包,我们可以使 ...
- 乐鑫代理-启明云端分享ESP32系列教程之二:Linux搭建esp-idf环境
提示:此教程依据乐鑫官方的ESP32入门教程总结而来,仅供个人参考学学习,如有错误,欢迎批评指正.乐鑫官方参考: 乐鑫官方文档地址 1.搭建esp-idf环境 1.1安装虚拟机与Ubuntu 未安装请 ...
- 10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10]
10 51单片机汇编:让定时器产生中断(使用Keil模拟器)[系列教程之10] 该系列主仓库地址:https://gitee.com/langcai1943/8051-from-boot-to-app ...
- 一步一步实现STM32-FOTA系列教程之FLASH静态区读写
一步一步实现STM32-FOTA系列教程之FLASH静态区读写 文章系列链接 <一步一步实现STM32-FOTA系列教程之bin文件生成> <一步一步实现STM32-FOTA系列教程 ...
- 一步一步实现STM32-FOTA系列教程之Bootloader编写
一步一步实现STM32-FOTA系列教程之Bootloader编写 文章系列链接 <一步一步实现STM32-FOTA系列教程之bin文件生成> <一步一步实现STM32-FOTA系列 ...
最新文章
- 关于ceph源码 backtrace 打印函数调用栈
- 十六届智能车全向组硬件开源 | 上海海事大学全向行进组
- 计算机16进制应用,16进制计算器安装方法 16进制计算器使用技巧
- scala 环境变量_Scala变量的范围
- 外媒:华为或将在2月24日发布麒麟820 支持5G网络
- 《spring-boot学习》-14-spring boot整合freeMarker模板
- 如何在java输入_怎么在java中编写输入语句?
- python基础编程语法-Python编程入门——基础语法详解
- pandas及numpy笔记
- 为什么BGP需要TCP三次握手?
- Spark 学习(三) RDD基本介绍
- fin.is_open()与fin.open()
- Atitit.异常机制的设计原理
- Vissim安装及配置详解
- 分享电脑中截图的五种方法(包括截长图)
- SpringBoot统一返回result结果集
- 解读《Superhuman AI for multiplayer poker》
- 什么是漏洞?最全的漏洞分类!
- RMS TO EAP通过MQTT简单实现(2)
- 简单理解Callable接口
热门文章
- 疯狂吸金1600个亿的拼多多,社交网络分析到底隐藏多少财富?
- python中使用什么表示代码块、不需要使用大括号_Python3学习笔记02-基础语法
- JVM【带着问题去学习 02】数据结构栈+本地方法栈+虚拟机栈+JVM栈运行原理
- 添加轨迹运动_时间最优轨迹(资料)
- python画图颜色表示大小变化_python画图(线条颜色、大小、类型:点、虚线等)(图文详细入门教程四)...
- pandas 索引_Pandas学习笔记03数据清洗(通过索引选择数据)
- three.js两个点给线条加宽度_108m2家里镶金线条,就是不一样,装出大宅范!太美了!晒晒...
- 关于linux的服务器搭建,关于搭建linux日志服务器
- Spring的事务控制-基于注解的方式
- C#——实现IComparable接口、IComparableT 接口、IComparer接口、IComparerT 接口和ComparerT 类DEMO