@RolesAllowed 与 @PreAuthorize 与 @Secured

Posted

技术标签:

【中文标题】@RolesAllowed 与 @PreAuthorize 与 @Secured【英文标题】:@RolesAllowed vs. @PreAuthorize vs. @Secured 【发布时间】:2017-10-13 04:24:55 【问题描述】:

我有一个基本的 SpringBoot 应用程序。使用 Spring Initializer、嵌入式 Tomcat、Thymeleaf 模板引擎,并打包为可执行 JAR 文件。

我想保护控制器:

@Controller
@RequestMapping("/company")
@RolesAllowed("ROLE_ADMIN")
@PreAuthorize("hasRole('ADMIN')")
@Secured("ADMIN")
public class CompanyController 

我知道有不同的选择,但我真的不知道我应该使用哪个

【问题讨论】:

【参考方案1】:

安全注释

所有@PreAuthorize@RolesAllowed@Secured 都是允许配置方法安全性的注释。它们可以应用于单个方法或类级别,在后一种情况下,安全约束将应用于类中的所有方法。

使用Spring AOP proxies 实现方法级安全性。

@PreAuthorize

@PreAuthorize 注释允许使用 Spring 表达式语言 (SpEL) 指定对方法的访问约束。这些约束在方法被执行之前被评估,如果约束没有被满足,可能会导致方法的执行被拒绝。 @PreAuthorize 注解是 Spring Security 框架的一部分。

为了能够使用@PreAuthorizeprePostEnabled 属性在 @EnableGlobalMethodSecurity注解需要设置为true

@EnableGlobalMethodSecurity(prePostEnabled=true)

@RolesAllowed

@RolesAllowed 注解起源于JSR-250 Java 安全标准。这 注释@PreAuthorize 注释更受限制,因为它只支持基于角色的安全性

为了使用@RolesAllowed注解,包含这个注解的库需要在类路径中,因为它不是Spring Security的一部分。另外@EnableGlobalMethodSecurity注解的jsr250Enabled属性需要设置为true

@EnableGlobalMethodSecurity(jsr250Enabled=true)

@Secured

@Secured 注释是一个传统的 Spring Security 2 注释,可用于配置方法安全性。它不仅支持基于角色的安全性,而且不支持使用 Spring 表达式语言 (SpEL) 来指定安全性约束。建议在新应用程序中使用@PreAuthorize 注释而不是此注释。

@Secured注解的支持需要在 使用 securedEnabled 属性的@EnableGlobalMethodSecurity 注释:

@EnableGlobalMethodSecurity(securedEnabled=true)

哪些安全注解允许使用 SpEL

下表显示了可与 Spring Security 5 一起使用的安全注解中对 Spring Expression Language 的支持:

╔═════════════════════╦═══════════════════╗
║ Security Annotation ║ Has SpEL Support? ║
╠═════════════════════╬═══════════════════╣
║  @PreAuthorize      ║        yes        ║
╠═════════════════════╬═══════════════════╣
║  @PostAuthorize     ║        yes        ║
╠═════════════════════╬═══════════════════╣
║  @PreFilter         ║        yes        ║
╠═════════════════════╬═══════════════════╣
║  @PostFilter        ║        yes        ║
╠═════════════════════╬═══════════════════╣
║  @Secured           ║        no         ║
╠═════════════════════╬═══════════════════╣
║  @RolesAllowed      ║        no         ║
╚═════════════════════╩═══════════════════╝

【讨论】:

【参考方案2】:

@Secured@RolesAllowed 在 Spring 中执行相同的功能。区别在于 @Secured 是 Spring 特定的注解,而 @RolesAllowed 是 Java 标准注解 (JSR250)。这些注释都不支持 SpEL。

@PreAuthorize 是另一个 Spring 特定的注解。您可以使用 SpEL 使用 @PreAuthorize 执行更强大的操作。您可以根据角色/权限、当前经过身份验证的用户以及传递给方法的参数来编写限制方法调用的表达式。

@PreAuthorize("hasRole('ADMIN') or #user.id == authentication.name")
public void deleteUser(User user) 
    ...

http://docs.spring.io/autorepo/docs/spring-security/4.0.x/reference/html/el-access.html#el-common-built-in


至于使用哪个,这完全取决于您。 @Secure@PreAuthorize 会将您的代码绑定到 Spring。如果绑定 Spring 不是问题,或者您需要执行更强大的操作,请使用 @PreAuthorize

【讨论】:

【参考方案3】:

所有这些对于您的目的来说基本相同,但@PreAuthorize 最适合控制器和控制器方法。 @Secured@RolesAllowed 用于描述服务层安全属性。

还要注意@PreAuthorize 注解必须定义一个配置类:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration 
...

【讨论】:

以上是关于@RolesAllowed 与 @PreAuthorize 与 @Secured的主要内容,如果未能解决你的问题,请参考以下文章

@RolesAllowed() 在 keycloak 中检查啥角色

@RolesAllowed、@DenyAll 在 Web 层中的使用?

使用 Enum 类型作为 @RolesAllowed-Annotation 的值参数

Spring Security应用开发(20)基于方法的授权使用@RolesAllowed注解

将@RolesAllowed 注释应用于存储在数据库中的现有用户

在 SpringBoot 应用程序中使用 @RolesAllowed 的异常