我正在尝试使用类型级别的@PreAuthorize
注释来保护Controller,并尝试通过使用不同的@PreAuthorize
注释某些方法来覆盖该行为。然而,问题是,Spring首先评估方法注释(授予访问权限),然后评估类注释(拒绝访问)。
有没有办法扭转这个顺序?我还想不出来。
编辑:
在方法级别,我只想授予对非注册用户的访问权限:
@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()
,从而导致授予访问权限并立即再次拒绝访问。
答案 0 :(得分:14)
感谢您的所有回复。 然而,答案完全不同:)
我把它放在这里以防其他人遇到同样的问题。
我在@InitBinder
带注释的方法中注册了自定义验证程序。在控制器上请求的方法调用之后调用此绑定方法。由于此绑定方法未使用@PreAuthorize
注释,因此请求被拒绝。
解决方案是注释绑定方法,如下所示:
@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
然后,我的OP调用的方法调用就像预期的那样。
答案 1 :(得分:5)
问题不在于您需要更改授予和拒绝的顺序。问题很简单,方法级别注释覆盖类级别注释。
PrePostAnnotationSecurityMetadataSource
Java Doc:
可以在类或方法上指定注释,并且特定于方法的注释将优先。
此逻辑的具体实现是在类findAnnotation
的方法PrePostAnnotationSecurityMetadataSource
中完成的。 (不幸的是,这种方法是私有的。)
所以你可以编写自己的MethodSecurityMetadataSource
,如果你看一下PrePostAnnotationSecurityMetadataSource
的代码,你会发现它有多容易。
但最后有一个警告:结束:困难的任务不是重写方法,困难的任务是将新的MethodSecurityMetadataSource
“注入”安全系统。我相信你无法使用spring安全命名空间配置,所以你需要通过显式bean声明替换spring安全命名空间。