@PreAuthorize 为什么有时候不生效?类内部调用会不会绕过?@PostAuthorize 是方法执行前还是执行后检查?@Secured 还能用吗?这篇在 Spring Boot 4.0.8、Spring Security 7 上用同一个 Service 把各种情况都跑一遍。
Svc 的实际类型:Svc$$SpringCGLIB$$0;是不是 AOP 代理:true;是不是 CGLIB 代理:true alice(ROLE_USER)调 admin() ⇒ 抛 AuthorizationDeniedException:Access Denied root(ROLE_ADMIN)调 admin() ⇒ admin 的数据 没有登录(SecurityContext 里没有 Authentication)调 admin() ⇒ 抛 AuthenticationCredentialsNotFoundException:An Authentication object was not found in the SecurityContext alice 调 outer()(类内部 this.admin()) ⇒ outer 里调 this.admin() → admin 的数据 alice 调 pkgPrivate()(同包,package-private) ⇒ 抛 AuthorizationDeniedException:Access Denied alice 调 callPriv()(public 方法里调 private 的 priv()) ⇒ private 方法执行了 alice 调 viaIface()(注解写在接口上) ⇒ 抛 AuthorizationDeniedException:Access Denied
CGLIB 代理;自调用、private 方法绕过;接口上的注解有效。
alice 调 mine("alice") ⇒ 只能看自己的:alice
alice 调 mine("bob") ⇒ 抛 AuthorizationDeniedException:Access Denied
alice 调 doc("alice")(@PostAuthorize) ⇒ Doc[owner=alice, text=内容]
alice 调 doc("bob")(方法已经执行,返回值被拒绝) ⇒ 抛 AuthorizationDeniedException:Access Denied
alice 调 count(三个文档,两个属于 bob)(@PreFilter) ⇒ 1
alice 调 all()(@PostFilter) ⇒ [Doc[owner=alice, text=a1], Doc[owner=alice, text=a2]]
alice 调 count(不可变列表 List.of)(@PreFilter 要原地删元素) ⇒ 2参数名、返回值、集合过滤;@PostAuthorize 方法体先执行。
手工构造的 Authentication 调 factor()(authorities 只有 ROLE_USER) ⇒ 抛 AuthorizationDeniedException:Access Denied
Spring Security 7 认证后多出的权限,手工构造的 Authentication 要自己带上。
alice 调 secured() (默认的 @EnableMethodSecurity) ⇒ @Secured 方法执行了 alice 调 rolesAllowed() (默认的 @EnableMethodSecurity) ⇒ @RolesAllowed 方法执行了 root 调 secured() (默认的 @EnableMethodSecurity) ⇒ @Secured 方法执行了 alice 调 secured() (@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)) ⇒ 抛 AuthorizationDeniedException:Access Denied alice 调 rolesAllowed() (@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)) ⇒ 抛 AuthorizationDeniedException:Access Denied root 调 secured() (@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)) ⇒ @Secured 方法执行了
@Secured、@RolesAllowed 默认不生效,要显式打开。