默认情况下, Spring Security 并不启用方法级的安全管控. 启用方法级的管控后, 可以针对不同的方法通过注解设置不同的访问条件.
Spring Security 支持三种方法级注解, 分别是 JSR-205 注解/@Secured 注解/prePostEnabled注解. 这些注解不仅可以直接加 controller 方法上, 也可以注解 Service 或 DAO 类中的方法. 

启用方法级的管控代码是, 新建一个 WebSecurityConfigurerAdapter Configuration 类, 加上 @EnableGlobalMethodSecurity() 注解, 通过@EnableGlobalMethodSecurity 参数开启相应的方法级的管控.

===================================
JSR-205 注解
===================================
通过 @EnableGlobalMethodSecurity(jsr250Enabled=true), 开启 JSR-205 注解.

@DenyAll 注解, 拒绝所有的访问
@PermitAll 注解, 运行所有访问
@RolesAllowed({"USER","ADMIN"}), 该方法只允许有 ROLE_USER 或 ROLE_ADMIN 角色的用户访问.

===================================
@Secured 注解
===================================
通过 @EnableGlobalMethodSecurity(securedEnabled=true), 开启 @Secured 注解.
只有满足角色的用户才能访问被注解的方法, 否则将会抛出 AccessDenied 异常.
例子:
@Secured("ROLE_TELLER","ROLE_ADMIN"), 该方法只允许 ROLE_TELLER 或 ROLE_ADMIN 角色的用户访问.
@Secured("IS_AUTHENTICATED_ANONYMOUSLY"), 该方法允许匿名用户访问.

===================================
@PreAuthorize 类型的注解(支持 Spring 表达式)
===================================
@EnableGlobalMethodSecurity(prePostEnabled=true), 开启 prePostEnabled 相关的注解.
JSR-205 和 @Secured 注解功能较弱, 不支持 Spring EL 表达式. 推荐使用 @PreAuthorize 类型的注解.
具体有4个注解.
@PreAuthorize 注解, 在方法调用之前, 基于表达式结果来限制方法的使用.
@PostAuthorize 注解, 允许方法调用, 但是如果表达式结果为 false, 将抛出一个安全性异常.
@PostFilter 注解, 允许方法调用, 但必要按照表达式来过滤方法的结果.
@PreFilter 注解, 允许方法调用, 但必须在进入方法之前过来输入值.

例子:
@PreAuthorize("hasRole('ADMIN')") //必须有 ROLE_ADMIN 角色
public void addBook(Book book);

//必须同时具备 ROLE_ADMIN 和 ROLE_DBA 角色
@PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
public void addBook(Book book);

@PreAuthorize ("#book.owner == authentication.name")
public void deleteBook(Book book);

@PostAuthorize ("returnObject.owner == authentication.name")
public Book getBook();

===================================
@PreAuthorize 表达式
===================================
1. returnObject 保留名
对于 @PostAuthorize 和 @PostFilter 注解, 可以在表达式中使用 returnObject 保留名, returnObject 代表着被注解方法的返回值, 我们可以使用 returnObject 保留名对注解方法的结果进行验证.
比如:
@PostAuthorize ("returnObject.owner == authentication.name")
public Book getBook();

2. 表达式中的 # 号
在表达式中, 可以使用 #argument123 的形式来代表注解方法中的参数 argument123.
比如:
@PreAuthorize ("#book.owner == authentication.name")
public void deleteBook(Book book);

还有一种 #argument123 的写法, 即使用 Spring Security @P注解来为方法参数起别名, 然后在 @PreAuthorize 等注解表达式中使用该别名. 不推荐这种写法, 代码可读性较差.
@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);

3. 内置表达式有:

表达式 备注
hasRole([role]) 如果有当前角色, 则返回 true(会自动加上 ROLE_ 前缀)
hasAnyRole([role1, role2]) 如果有任一角色即可通过校验, 返回true,(会自动加上 ROLE_ 前缀)
hasAuthority([authority]) 如果有指定权限, 则返回 true
hasAnyAuthority([authority1, authority2]) 如果有任一指定权限, 则返回true
principal  获取当前用户的 principal 主体对象 
authentication  获取当前用户的 authentication 对象, 
permitAll   总是返回 true, 表示全部允许
denyAll  总是返回 false, 代表全部拒绝
isAnonymous()  如果是匿名访问, 返回true
isRememberMe()  如果是remember-me 自动认证, 则返回 true
isAuthenticated()  如果不是匿名访问, 则返回true
isFullAuthenticated()  如果不是匿名访问或remember-me认证登陆, 则返回true
hasPermission(Object target, Object permission)  
hasPermission(Object target, String targetType, Object permission)   
   

===================================
示例代码
===================================

----------------------------
pom.xml
----------------------------

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

----------------------------
SecurityConfig 配置类
----------------------------
SecurityConfig 配置类开启方法级管控(仅启用 prePostEnabled 类的注解), 并 hard coded 了一个内置的用户清单.

因为没有重载 configure(HttpSecurity http) 方法, 用的是Spring security 的 basic Authentication 和内置的login form.

@EnableWebSecurity
@Configuation
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override
public void configure(AuthenticationManagerBuilder builder)
throws Exception {
builder.inMemoryAuthentication()
.withUser("123").password("123").roles("USER")
.and()
.withUser("ADMIN").password("ADMIN").roles("ADMIN")
.and()
.withUser("124").password("124").roles("USER2");
} @SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}

----------------------------
BookService 配置类
----------------------------
为BookService Service类的方法加上 @PreAuthorize 注解, 对权限进行控制.

@Service
class BookService{
@PreAuthorize("hasRole('ADMIN')")
public void addBook(Book book) {
System.out.println("you have added a book successfully");
} @PreAuthorize("hasAnyRole('ADMIN','USER')")
public Book getBook() {
Book book=new Book("A");
return book ;
} @PreAuthorize("hasRole('ADMIN')")
public void deleteBook(Book book) {
System.out.println("Book deleted");
}
}

----------------------------
Entity 和 Controller 类
----------------------------
Entity 和 Controller 类没有特别之处, 这里不用太关注.

@RestController("/")
class BookController{ @Autowired
private BookService bookService ; @GetMapping("/get")
public String getBook() {
Book book =bookService.getBook() ;
return book.getName() ;
}
} class Book{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Book(String name) {
this.name=name ;
}
}

----------------------------
测试结果
----------------------------
使用 123 用户(角色是 USER )登陆, 可以访问 http://localhost:8080/get ; 使用 124 用户(角色是 USER2 )登陆, 访问 http://localhost:8080/get 报下面的403权限问题. 符合预期

===================================
参考
===================================
https://www.concretepage.com/spring/spring-security/preauthorize-postauthorize-in-spring-security
https://www.jianshu.com/p/bcb3c6445b2b
https://www.jianshu.com/p/41b7c3fb00e0
https://blog.csdn.net/l18767118724/article/details/72934564
https://spring.io/guides/topicals/spring-security-architecture/
https://www.logicbig.com/tutorials/spring-framework/spring-security/roles-allowed-annotation.html

Spring Security 之方法级的安全管控的更多相关文章

  1. spring security 方法权限使用

    前面我们讲过了使用<security:intercept-url>配置url的权限访问,下面我们讲解一下基于方法的权限使用默认情况下, Spring Security 并不启用方法级的安全 ...

  2. Spring Security方法级别授权使用介绍

    1.简介 简而言之,Spring Security支持方法级别的授权语义. 通常,我们可以通过限制哪些角色能够执行特定方法来保护我们的服务层 - 并使用专用的方法级安全测试支持对其进行测试. 在本文中 ...

  3. Spring Security 4 使用@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全

    [相关已翻译的本系列其他文章,点击分类里面的spring security 4] 上一篇:Spring Security 4 整合Hibernate 实现持久化登录验证(带源码) 原文地址:http: ...

  4. Spring Security(17)——基于方法的权限控制

    目录 1.1     intercept-methods定义方法权限控制 1.2     使用pointcut定义方法权限控制 1.3     使用注解定义方法权限控制 1.3.1    JSR-25 ...

  5. Spring Security教程之基于方法的权限控制(十二)

    目录 1.1     intercept-methods定义方法权限控制 1.2     使用pointcut定义方法权限控制 1.3     使用注解定义方法权限控制 1.3.1    JSR-25 ...

  6. Spring Security 5.0.x 参考手册 【翻译自官方GIT-2018.06.12】

    源码请移步至:https://github.com/aquariuspj/spring-security/tree/translator/docs/manual/src/docs/asciidoc 版 ...

  7. 【JavaEE】SSH+Spring Security基础上配置AOP+log4j

    Spring Oauth2大多数情况下还是用不到的,主要使用的还是Spring+SpringMVC+Hibernate,有时候加上SpringSecurity,因此,本文及以后的文章的example中 ...

  8. Spring Security 入门详解(转)

    1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别 处理 ...

  9. Spring Security(三十):9.5 Access-Control (Authorization) in Spring Security

    The main interface responsible for making access-control decisions in Spring Security is the AccessD ...

随机推荐

  1. Python爬虫【解析库之beautifulsoup】

    解析库的安装 pip3 install beautifulsoup4 初始化 BeautifulSoup(str,"解析库") from bs4 import BeautifulS ...

  2. android的listview以及画线--to thi tha

    https://www.cnblogs.com/896240130Master/p/6135165.html 这个的 https://www.jianshu.com/p/5522470760c1

  3. JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)_javascript技巧_

    JS获取屏幕,浏览器窗口大小,网页高度宽度(实现代码)_javascript技巧_--HTML5中文学习网 http://www.html5cn.com.cn/shili/javascripts/79 ...

  4. python之三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    一 三元表达式.列表推导式.生成器表达式 一 三元表达式 name=input('姓名>>: ') res='SB' if name == 'alex' else 'NB' print(r ...

  5. SQL CREATE TABLE 语句

    CREATE TABLE 语句 CREATE TABLE 语句用于创建数据库中的表. SQL CREATE TABLE 语法 CREATE TABLE 表名称 ( 列名称1 数据类型, 列名称2 数据 ...

  6. Push rejected: Push to origin/master was rejected错误解决方案

    解决方案如下: 1.切换到自己项目所在的目录,右键选择GIT BASH Here,Idea中可使用Alt+F12 2.在terminl窗口中依次输入命令: git pull git pull orig ...

  7. Luogu5058 [ZJOI2004]嗅探器

    $Luogu5058 [ZJOI2004]嗅探器 给定一张 \(n\) 个点, \(m\) 条边的无向图,和两点 \(s,\ t\) ,求 \(s\to t\) 编号最小的必经点(排除 \(s,\ t ...

  8. go笔记-pprof使用

    go tool pprof http://localhost:6060/debug/pprof/profile go tool pprof http://localhost:6060/debug/pp ...

  9. Linux内存管理 (4)分配物理页面

    专题:Linux内存管理专题 关键词:分配掩码.伙伴系统.水位(watermark).空闲伙伴块合并. 我们知道Linux内存管理是以页为单位进行的,对内存的管理是通过伙伴系统进行. 从Linux内存 ...

  10. SpringBoot系列十:SpringBoot整合Redis

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合 Redis 2.背景 Redis 的数据库的整合在 java 里面提供的官方工具包:jed ...