跳至主要內容

基于方法的授权

Jin大约 2 分钟

基于方法的授权

1、启用方法安全

@Configuration
@EnableMethodSecurity
public class SecurityConfig {
//...
}

2、基于注解的授权方法

2.1、@PreAuthorize

  • 在方法执行之前进行复杂的权限检查。

代码示例:

@Service
public class MyService {

    // 只有拥有 'ROLE_ADMIN' 权限的用户才能访问
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void adminMethod() {
        // 执行需要管理员权限的方法
    }

    // 只有拥有 'ROLE_USER' 或 'ROLE_ADMIN' 权限的用户才能访问
    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
    public void userOrAdminMethod() {
        // 执行需要用户或管理员权限的方法
    }

    // 只有当前用户拥有 'edit' 权限才能访问
    @PreAuthorize("hasPermission(#document, 'edit')")
    public void editDocument(Document document) {
        // 执行编辑文档的方法
    }

    // 只有当前用户名是 'alice' 的用户可以访问
    @PreAuthorize("principal.username == 'alice'")
    public void userMethod() {
        // 执行仅对 alice 可见的方法
    }
}

2.2、@Secured

@Secured 注解比较简单,通常用于角色控制。它不能像 @PreAuthorize 一样使用复杂的 SpEL 表达式,但适用于基于角色的控制。

代码示例:

@Service
public class MyService {

    // 只有 'ROLE_ADMIN' 角色的用户可以访问
    @Secured("ROLE_ADMIN")
    public void adminMethod() {
        // 执行管理员方法
    }

    // 只有 'ROLE_USER' 或 'ROLE_ADMIN' 角色的用户可以访问
    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public void userOrAdminMethod() {
        // 执行用户或管理员方法
    }
}

2.3、@PostAuthorize

@PostAuthorize 注解用于在方法执行后进行授权判断,它与 @PreAuthorize 相反,后者是在方法执行前进行授权检查。@PostAuthorize 可以用于在方法执行后基于返回值或其他条件进行安全控制。

示例:

    @PostAuthorize("returnObject.owner == authentication.name")
    public Document getDocument(Long documentId) {
        // 返回的文档的 owner 必须是当前认证用户
        return documentRepository.findById(documentId).orElseThrow(() -> new DocumentNotFoundException(documentId));
    }

2.4、@RolesAllowed

@RolesAllowedJava EE 标准注解,它允许指定允许访问方法的角色,可以使用在类或方法级别。

	@RolesAllowed("ROLE_ADMIN")
    public void performAdminTask() {
        // 仅允许 ROLE_ADMIN 角色的用户执行该方法
    }

    @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
    public void performUserTask() {
        // 允许 ROLE_USER 和 ROLE_ADMIN 角色的用户执行该方法
    }

配置权限表达式

Spring Security 6.x 支持多种权限控制表达式,允许你定义复杂的授权条件:

  • hasRole('ROLE_ADMIN'): 检查当前用户是否拥有 ROLE_ADMIN 角色。
  • hasAuthority('ROLE_ADMIN'): 检查当前用户是否有 ROLE_ADMIN 权限(权限和角色不同,hasAuthority 可以用于更细粒度的权限控制)。
  • isAuthenticated(): 检查用户是否已经认证。
  • isAnonymous(): 检查用户是否是匿名用户。
  • permitAll(): 允许所有人访问。
  • denyAll(): 拒绝所有人访问。

结合表达式

SpEL(Spring Expression Language)表达式可以组合各种权限判断,进行细粒度的控制。例如:

@PreAuthorize("hasRole('ROLE_ADMIN') or (hasRole('ROLE_USER') and #username == authentication.name)")
public void updateProfile(String username) {
    // 允许ROLE_ADMIN 角色用户访问,或者ROLE_USER角色且用户名与当前用户一致时访问
}
贡献者: Jin