1. 基本知识
在java中,@PreAuthorize
是Spring Security框架中的一个注解,用于在方法调用之前对用户的权限进行验证。
允许在方法级别定义访问控制规则,确保只有满足指定条件的用户才能调用该方法
这个注解通常与Spring的AOP(面向切面编程)结合使用,推荐阅读:
- Spring框架从入门到学精(全)
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
本身的作用主要如下:
- 权限控制: 主要用于实现基于方法调用的权限控制,确保只有经过验证的用户才能访问受保护的方法
- 条件判断: 允许在注解中定义条件表达式,这些表达式决定是否允许方法调用
使用方式:
@PreAuthorize
注解的参数是一个 SpEL(Spring Expression Language)表达式,用于定义权限规则(SpEL支持在表达式中使用各种功能,包括方法调用、条件判断等)
表达式的结果应该是布尔值,如果为 true,则允许方法调用,否则抛出权限异常。
示例:@PreAuthorize("hasRole('ROLE_ADMIN')")
表示只有具有 ROLE_ADMIN
角色的用户可以调用该方法。
除了在方法级别使用 @PreAuthorize
,还可以在全局配置中定义方法安全性
通过配置类,指定应用于整个应用程序的全局安全性规则。
2. 使用方式
要么以配置类要么直接使用
2.1 配置类
如果通过配置类的方式:
一般通过继承 WebSecurityConfigurerAdapter
类,通过这个类配置应用程序的安全性
大致的Demo如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 配置内存中的用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
// 配置访问控制规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
一个是普通用户,一个是管理员。
访问控制规则指定了 /admin/**
路径需要具有 “ADMIN” 角色的用户才能访问/user/**
路径需要具有 “USER” 角色的用户才能访问
其他请求需要身份验证。登录页面配置为 /login
,注销行为允许所有用户。
整体对于配置类来说:
-
定义认证规则: 指定用户认证的规则、设置用户的身份验证方式,例如基于内存、数据库、LDAP 等方式,并定义用户的角色和权限
-
配置访问控制规则:哪些路径需要身份验证,哪些路径允许匿名访问,哪些路径需要特定的角色或权限
-
定制登录和注销行为: 自定义登录页面、处理登录请求的 URL、注销行为等
-
启用或禁用特定的安全性功能: 启用或禁用各种安全性功能,例如 CSRF 保护、Session 管理等
2.2 直接使用
内部内置的方法,都在这个类上:
@PreAuthorize
注解内置了一些方便的方法,可以直接在表达式中使用,例如:
-
hasRole('ROLE_NAME')
检查用户是否具有指定角色。 -
hasAnyRole('ROLE1', 'ROLE2')
检查用户是否具有给定角色中的任意一个。 -
hasAuthority('AUTHORITY_NAME')
检查用户是否具有指定权限。 -
hasAnyAuthority('AUTHORITY1', 'AUTHORITY2')
检查用户是否具有给定权限中的任意一个。 -
hasPermission(targetObject, 'permission')
: 检查用户是否具有特定对象的特定权限。
如图所示:
对于上述方法的基本细节操作如下:
方法参数传递:
在表达式中,可以引用方法的参数,例如:@PreAuthorize("hasPermission(#entity, 'read')")
表示检查用户是否有对给定实体的读权限。
逻辑运算:
表达式支持逻辑运算符,如 and, or, not,允许构建更复杂的权限规则
@PreAuthorize("hasRole('ADMIN') and hasPermission(#entity, 'write')")
大致Demo如下:
import org.springframework.security.a***ess.prepost.PreAuthorize;
public class MyService {
// 示例1: 仅允许具有ROLE_ADMIN角色的用户调用
@PreAuthorize("hasRole('ROLE_ADMIN')")
public void adminOperation() {
// 实现管理员操作的代码
}
// 示例2: 允许具有READ权限并且是特定用户的调用
@PreAuthorize("hasPermission(#username, 'READ')")
public void userOperation(String username) {
// 实现用户操作的代码
}
}
@PreAuthorize
注解用于控制方法的访问权限。
- 只有具有
ROLE_ADMIN
角色的用户才能调用adminOperation
方法 - 只有具有
READ
权限并且传入的用户名符合条件的用户才能调用userOperation
方法