SpringSecurity中WebSecurity和HttpSecurity的关系-SpringSecurity的注解访问权限控制-《Java笔记》

admin 2025-10-19 04:33:54 编程 来源:ZONE.CI 全球网 0 阅读模式

Java Spring Spring SecuritySpring Security提供基于注解的访问控制。

开启方法注解访问控制

Spring Security默认是关闭方法注解的,开启它只需要通过引入@EnableGlobalMethodSecurity注解即可:

  1. /**
  2. * 开启方法安全注解
  3. *
  4. */
  5. @EnableGlobalMethodSecurity(prePostEnabled = true,
  6. securedEnabled = true,
  7. jsr250Enabled = true)
  8. public class MethodSecurityConfig {
  9. }

@EnableGlobalMethodSecurity 提供了 prePostEnabledsecuredEnabledjsr250Enabled 三种方式,可以根据需要选择使用这三种的一种或者其中几种。

@EnableGlobalMethodSecurity

@EnableGlobalMethodSecurity的思维导图梳理相关的逻辑。Spring Security的注解访问权限控制 - 图1黄色区域是注解访问控制的基本知识点,需要重点掌握,先来看看基本的用法。

@PreAuthorize@PostAuthorize

prePostEnabled等于true时启用。在标记的方法调用之前或者之后,通过SpEL表达式来计算是否可以调用方法或者调用后是否可以返回结果。总结了一些常用的表达式样例:

SpEL表达式 说明
principal.username ne 'fcant' 当前principal的username不能是fcant
authentication.authorities.contains('ROLE_ADMIN') 当前Authentication的authorities包含ROLE_ADMIN
hasRole('ADMIN') 当前用户必须有角色ROLE_ADMIN,等同于上面
hasAnyRole('ADMIN','USER') 当前用户角色必须有ROLE_ADMIN或者ROLE_USER
hasAuthority('ROLE_ADMIN') 同hasRole
hasAnyAuthority('ROLE_ADMIN','ROLE_USER') 同hasAnyRole
#requestParam eq 'fcant' 当前请求参数requestParam(可以是对象,这里是字符串示例)值等于fcant

其它表达式可参考SpEL官方文档。如果用户fcant访问下面这个接口,方法不但不执行还会403

  1. /**
  2. * 当前用户名不是fcant才能访问 否则403
  3. * @param req req
  4. * @return map
  5. */
  6. @GetMapping("/prepost")
  7. @PreAuthorize("authentication.principal.username ne 'fcant'")
  8. public Map<String, String> prepost(String req){
  9. Map<String, String> map = Collections.singletonMap("req", req);
  10. System.out.println("map = " + map);
  11. return map;
  12. }

如果方法上的注解改为@PostAuthorize("authentication.principal.username ne 'fcant'"),控制台会打印Spring Security的注解访问权限控制 - 图2从日志上可以明显看出方法确实执行了,但是还是给了403

@PreFilter@PostFilter

prePostEnabled等于true时启用。这两个注解可以看做@PreAuthorize@PostAuthorize的加强版。它们除了能实现@PreAuthorize@PostAuthorize外还具有过滤请求响应数据的能力。限定处理的数据类型有Collection、数组、Map、Stream。举个例子:

  1. // ids = ["fcant","fcant","jetty"]
  2. @PostMapping("/prefilter")
  3. @PreFilter(value = "hasRole('ADMIN') and filterObject.startsWith('f')",
  4. filterTarget = "ids")
  5. public Collection<String> preFilter(@RequestBody Collection<String> ids){
  6. // ids = ["fcant"]
  7. System.out.println("ids = " + ids);
  8. return ids;
  9. }

上面的接口方法有两层含义:

  • 当前用户必须持有角色ROLE_ADMIN,否则方法不执行。这一条件不存在的话方法一定会执行。
  • 如果方法执行的话,入参ids集合中不包含f开头的元素都会被移除,返回值为fcant。

过滤元素的底层是java.util.Collection#remove(Object);另外多个入参需要使用filterTarget指定参数名称。@PostFilter也很好理解,拿下面的方法来说:

  1. @GetMapping("/postfilter")
  2. @PostFilter("hasRole('ADMIN') and filterObject.startsWith('f')")
  3. public Collection<String> postfilter(){
  4. List<String> list = new ArrayList<>();
  5. list.add("fcantcn");
  6. list.add("fcant");
  7. list.add("fcant");
  8. // list = ["fcant"]
  9. System.out.println("list = " + list);
  10. return list;
  11. }

无论是否满足@PostFilter表达式的条件,都会打印list = ["fcant"],条件成立返回list,不成立则返回403。这两个注解用来控制请求和相应中集合、流中的数据。

@Secured

securedEnabled等于true时启用。该注解功能要简单得多,默认情况下只能基于角色(默认需要带前缀 ROLE_)集合来进行访问控制决策。该注解的机制是只要其声明的角色集合(value)中包含当前用户持有的任一角色就可以访问,也就是用户的角色集合和 @Secured 注解的角色集合要存在非空的交集。不支持使用 SpEL 表达式进行决策。过于简单不再演示。@Secured等同于hasAnyAuthority

JSR-250

jsr250Enabled等于true时启用。启用 JSR-250 安全控制注解,这属于 JavaEE 的安全规范(现为 jakarta 项目)。Spring Security中使用了JavaEE 安全注解中的以下三个:

  • **@DenyAll** 拒绝所有的访问
  • **@PermitAll** 同意所有的访问
  • **@RolesAllowed** 用法和上面的 @Secured 一样。

    注解控制的优劣

    使用注解的好处就是绑定了接口方法,控制粒度非常细,甚至能做一些数据层面的访问控制。劣势在于它是静态织入Java代码中的,灵活性难以把握。
以太坊cppgolang区别 编程

以太坊cppgolang区别

以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
progolang 编程

progolang

Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
golangn个发送者 编程

golangn个发送者

Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
golang技能图谱 编程

golang技能图谱

从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
评论:0   参与:  4