基于方法的授权
大约 2 分钟
基于方法的授权
1、启用方法安全
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
//...
}
2、基于注解的授权方法
@PreAuthorize
2.1、- 在方法执行之前进行复杂的权限检查。
代码示例:
@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() {
// 执行用户或管理员方法
}
}
@PostAuthorize
2.3、@PostAuthorize
注解用于在方法执行后进行授权判断,它与 @PreAuthorize
相反,后者是在方法执行前进行授权检查。@PostAuthorize
可以用于在方法执行后基于返回值或其他条件进行安全控制。
示例:
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long documentId) {
// 返回的文档的 owner 必须是当前认证用户
return documentRepository.findById(documentId).orElseThrow(() -> new DocumentNotFoundException(documentId));
}
@RolesAllowed
2.4、@RolesAllowed
是 Java 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角色且用户名与当前用户一致时访问
}