使用 @PreAuthorize 注解
如何开启 Security 基于注解的权限配置?
解决方案
java
package cloud.xuxiaowei.oauth2.config;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
/**
* 开启 Security 基于注解的权限配置
*
* @author xuxiaowei
* @since 0.0.1
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomSecurityConfig {
}
java
package cloud.xuxiaowei.oauth2.config;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
/**
* 开启 Security 基于注解的权限配置
* <p>
* 注意:
* <p>
* 1. 在 Spring Boot 3 中,
* <code>org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity</code>
* 被标记为过时
* <p>
* 2. {@link EnableMethodSecurity#prePostEnabled()} 默认值为 true,无需重复设置
*
* @author xuxiaowei
* @since 0.0.1
* @see org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
*/
@EnableMethodSecurity
public class CustomSecurityConfig {
}
使用方式 1:设置 authorities
为 无前缀
设置 authorities
为 无前缀
java
package cloud.xuxiaowei.oauth2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
/**
* Security 注解鉴权配置
*
* @author xuxiaowei
* @since 0.0.1
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class JwtAuthenticationConverterConfig {
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
// *** 省略
// 设置 authorities 前缀:使用无前缀模式
// 默认值:ROLE_
grantedAuthoritiesConverter.setAuthorityPrefix("");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
// *** 省略
return jwtAuthenticationConverter;
}
}
权限
与 角色
注解
用户 authorities | 检查权限 注解 | 是否允许 | 说明 |
---|---|---|---|
A1 | @PreAuthorize("hasAuthority('A1')") | ✅ | 用户拥有权限 A1 ,可以访问需要 A1 权限 的接口 |
A1 | @PreAuthorize("hasAnyAuthority('A1')") | ✅ | 用户拥有权限 A1 ,可以访问需要 A1 任意权限 的接口 |
A1 | @PreAuthorize("hasAnyAuthority('A1', 'A2')") | ✅ | 用户拥有权限 A1 ,可以访问需要 A1 或 A2 任意权限 的接口 |
A1 | @PreAuthorize("hasAuthority('A1') and hasAuthority('A2')") | ❌ | 用户拥有权限 A1 ,不 可以访问同时 需要 A1 和 A2 共同权限 的接口 |
A1 、A2 | @PreAuthorize("hasAuthority('A1')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 A1 权限 的接口 |
A1 、A2 | @PreAuthorize("hasAnyAuthority('A1')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 A1 任意权限 的接口 |
A1 、A2 | @PreAuthorize("hasAnyAuthority('A1', 'A2')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 A1 或 A2 任意权限 的接口 |
A1 、A2 | @PreAuthorize("hasAuthority('A1') and hasAuthority('A2')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问同时 需要 A1 和 A2 共同权限 的接口 |
A2 | @PreAuthorize("hasAuthority('A1')") | ❌ | 用户拥有权限 A2 ,不 可以访问需要 A1 权限 的接口 |
A2 | @PreAuthorize("hasAnyAuthority('A1')") | ❌ | 用户拥有权限 A2 ,不 可以访问需要 A1 任意权限 的接口 |
用户 authorities | 检查角色 注解 | 是否允许 | 说明 |
---|---|---|---|
ROLE_A1 | @PreAuthorize("hasAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 任意角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 或 ROLE_A2 任意角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')") | ❌ | 用户拥有角色 ROLE_A1 ,不 可以访问同时 需要 ROLE_A1 和 ROLE_A2 共同角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 任意角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 或 ROLE_A2 任意角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问同时 需要 ROLE_A1 和 ROLE_A2 共同角色 的接口 |
ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1')") | ❌ | 用户拥有角色 ROLE_A2 ,不 可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ❌ | 用户拥有角色 ROLE_A2 ,不 可以访问需要 ROLE_A1 任意角色 的接口 |
使用方式 2:设置 authorities
为 指定前缀
设置 authorities
为 指定前缀
java
package cloud.xuxiaowei.oauth2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
/**
* Security 注解鉴权配置
*
* @author xuxiaowei
* @since 0.0.1
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class JwtAuthenticationConverterConfig {
@Bean
public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setDefaultRolePrefix("SCOPE_");
return expressionHandler;
}
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
// *** 省略
// 设置 authorities 前缀:使用默认值模式
// 默认值:ROLE_
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
// *** 省略
return jwtAuthenticationConverter;
}
}
权限
与 角色
注解
用户 authorities | 检查权限 注解 | 是否允许 | 说明 |
---|---|---|---|
A1 | @PreAuthorize("hasAuthority('SCOPE_A1')") | ✅ | 用户拥有权限 A1 ,可以访问需要 SCOPE_A1 权限 的接口 |
A1 | @PreAuthorize("hasAnyAuthority('SCOPE_A1')") | ✅ | 用户拥有权限 A1 ,可以访问需要 SCOPE_A1 任意权限 的接口 |
A1 | @PreAuthorize("hasAnyAuthority('SCOPE_A1', 'SCOPE_A2')") | ✅ | 用户拥有权限 A1 ,可以访问需要 SCOPE_A1 或 SCOPE_A2 任意权限 的接口 |
A1 | @PreAuthorize("hasAuthority('SCOPE_A1') and hasAuthority('SCOPE_A2')") | ❌ | 用户拥有权限 A1 ,不 可以访问同时 需要 SCOPE_A1 和 SCOPE_A2 共同权限 的接口 |
A1 、A2 | @PreAuthorize("hasAuthority('SCOPE_A1')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 SCOPE_A1 权限 的接口 |
A1 、A2 | @PreAuthorize("hasAnyAuthority('SCOPE_A1')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 SCOPE_A1 任意权限 的接口 |
A1 、A2 | @PreAuthorize("hasAnyAuthority('SCOPE_A1', 'SCOPE_A2')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问需要 SCOPE_A1 或 SCOPE_A2 任意权限 的接口 |
A1 、A2 | @PreAuthorize("hasAuthority('SCOPE_A1') and hasAuthority('SCOPE_A2')") | ✅ | 用户拥有权限 A1 和 A2 ,可以访问同时 需要 SCOPE_A1 和 SCOPE_A2 共同权限 的接口 |
A2 | @PreAuthorize("hasAuthority('SCOPE_A1')") | ❌ | 用户拥有权限 A2 ,不 可以访问需要 SCOPE_A1 权限 的接口 |
A2 | @PreAuthorize("hasAnyAuthority('SCOPE_A1')") | ❌ | 用户拥有权限 A2 ,不 可以访问需要 SCOPE_A1 任意权限 的接口 |
用户 authorities | 检查角色 注解 | 是否允许 | 说明 |
---|---|---|---|
ROLE_A1 | @PreAuthorize("hasAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 任意角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 ,可以访问需要 ROLE_A1 或 ROLE_A2 任意角色 的接口 |
ROLE_A1 | @PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')") | ❌ | 用户拥有角色 ROLE_A1 ,不 可以访问同时 需要 ROLE_A1 和 ROLE_A2 共同角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 任意角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问需要 ROLE_A1 或 ROLE_A2 任意角色 的接口 |
ROLE_A1 、ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')") | ✅ | 用户拥有角色 ROLE_A1 和 ROLE_A2 ,可以访问同时 需要 ROLE_A1 和 ROLE_A2 共同角色 的接口 |
ROLE_A2 | @PreAuthorize("hasAuthority('ROLE_A1')") | ❌ | 用户拥有角色 ROLE_A2 ,不 可以访问需要 ROLE_A1 角色 的接口 |
ROLE_A2 | @PreAuthorize("hasAnyAuthority('ROLE_A1')") | ❌ | 用户拥有角色 ROLE_A2 ,不 可以访问需要 ROLE_A1 任意角色 的接口 |
基于 HttpSecurity 配置
参见:授权 URL