Spring Security在类型级别@PreAuthorize不能在方法级别被覆盖

2022-09-02 21:43:04

我正在尝试在类型级别使用注释保护控制器,并尝试通过使用不同的.然而,问题在于,Spring首先评估方法注释(授予访问权限),然后评估类注释(拒绝访问)。@PreAuthorize@PreAuthorize

有没有办法扭转这一顺序?我还搞不清。

编辑:

在方法级别,我只想向非注册用户授予访问权限:

@PreAuthorize("isAnonymous()")
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String renderCreateEntity(ModelMap model) {
    return userService.renderCreateEntity(model);
}

但是,此控制器的标准应该是仅允许完全经过身份验证的用户:

@Controller
@RequestMapping(value = "/user")
@PreAuthorize("isFullyAuthenticated()")
public class UserController { [...] }

在调试单步执行应用时,我看到首先对其进行了评估,从而导致授予访问权限并立即再次拒绝访问。isAnonymous()isFullyAuthenticated()


答案 1

感谢您的回复。然而,答案是完全不同的东西:)

我把这个放在这里,以防其他人有同样的问题。

我在带注释的方法中注册了一个自定义验证程序。此绑定方法是在控制器上请求的方法调用之后调用的。由于这个绑定方法没有被注释,这个请求被拒绝了。@InitBinder@PreAuthorize

解决方案是像这样注释绑定方法:

@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
    binder.setValidator(validator);
}

然后,来自我的OP的方法调用像预期的那样进行了评估。


答案 2

问题不在于您需要更改授予和拒绝的顺序。问题很简单,即方法级批注会覆盖类级批注。

PrePostAnnotationSecurityMetadataSourceJava Doc:

可以在类或方法上指定批注,并且特定于方法的批注将优先。

此逻辑的具体实现是在类的方法中完成的。(不幸的是,这种方法是私有的。findAnnotationPrePostAnnotationSecurityMetadataSource

所以你可以编写自己的 MethodSecurityMetadataSource,如果你看一下 的代码,你会看到它是多么容易。PrePostAnnotationSecurityMetadataSource

但最后有一个警告:最后:困难的任务不是重写方法,困难的任务是将新的MethodSecurityMetadataSource“注入”到安全系统中。我相信你不能用spring安全命名空间配置来做到这一点,所以你需要用显式bean声明来替换spring security命名空间。


推荐