Skip to content

使用 @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,可以访问需要 A1A2 任意权限 的接口
A1@PreAuthorize("hasAuthority('A1') and hasAuthority('A2')")用户拥有权限 A1可以访问同时需要 A1A2 共同权限 的接口
A1A2@PreAuthorize("hasAuthority('A1')")用户拥有权限 A1A2,可以访问需要 A1 权限 的接口
A1A2@PreAuthorize("hasAnyAuthority('A1')")用户拥有权限 A1A2,可以访问需要 A1 任意权限 的接口
A1A2@PreAuthorize("hasAnyAuthority('A1', 'A2')")用户拥有权限 A1A2,可以访问需要 A1A2 任意权限 的接口
A1A2@PreAuthorize("hasAuthority('A1') and hasAuthority('A2')")用户拥有权限 A1A2,可以访问同时需要 A1A2 共同权限 的接口
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_A1ROLE_A2 任意角色 的接口
ROLE_A1@PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')")用户拥有角色 ROLE_A1可以访问同时需要 ROLE_A1ROLE_A2 共同角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAuthority('ROLE_A1')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1 角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAnyAuthority('ROLE_A1')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1 任意角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1ROLE_A2 任意角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')")用户拥有角色 ROLE_A1ROLE_A2,可以访问同时需要 ROLE_A1ROLE_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_A1SCOPE_A2 任意权限 的接口
A1@PreAuthorize("hasAuthority('SCOPE_A1') and hasAuthority('SCOPE_A2')")用户拥有权限 A1可以访问同时需要 SCOPE_A1SCOPE_A2 共同权限 的接口
A1A2@PreAuthorize("hasAuthority('SCOPE_A1')")用户拥有权限 A1A2,可以访问需要 SCOPE_A1 权限 的接口
A1A2@PreAuthorize("hasAnyAuthority('SCOPE_A1')")用户拥有权限 A1A2,可以访问需要 SCOPE_A1 任意权限 的接口
A1A2@PreAuthorize("hasAnyAuthority('SCOPE_A1', 'SCOPE_A2')")用户拥有权限 A1A2,可以访问需要 SCOPE_A1SCOPE_A2 任意权限 的接口
A1A2@PreAuthorize("hasAuthority('SCOPE_A1') and hasAuthority('SCOPE_A2')")用户拥有权限 A1A2,可以访问同时需要 SCOPE_A1SCOPE_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_A1ROLE_A2 任意角色 的接口
ROLE_A1@PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')")用户拥有角色 ROLE_A1可以访问同时需要 ROLE_A1ROLE_A2 共同角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAuthority('ROLE_A1')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1 角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAnyAuthority('ROLE_A1')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1 任意角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAnyAuthority('ROLE_A1', 'ROLE_A2')")用户拥有角色 ROLE_A1ROLE_A2,可以访问需要 ROLE_A1ROLE_A2 任意角色 的接口
ROLE_A1ROLE_A2@PreAuthorize("hasAuthority('ROLE_A1') and hasAuthority('ROLE_A2')")用户拥有角色 ROLE_A1ROLE_A2,可以访问同时需要 ROLE_A1ROLE_A2 共同角色 的接口
ROLE_A2@PreAuthorize("hasAuthority('ROLE_A1')")用户拥有角色 ROLE_A2可以访问需要 ROLE_A1 角色 的接口
ROLE_A2@PreAuthorize("hasAnyAuthority('ROLE_A1')")用户拥有角色 ROLE_A2可以访问需要 ROLE_A1 任意角色 的接口

基于 HttpSecurity 配置

参见:授权 URL