无法在方法级别覆盖Spring Security的类型级别的@PreAuthorize

chz*_*gla 14 java spring spring-security

我正在尝试使用@PreAuthorize类型级别的注释来保护Controller,并尝试通过使用不同的方法注释某些方法来覆盖该行为@PreAuthorize.然而,问题是,Spring首先评估方法注释(授予访问权限),然后评估类注释(拒绝访问).

有没有办法扭转这种秩序?我还想不出来.

编辑:

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

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

但是,此Controller的标准应该是仅允许完全通过身份验证的用户:

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

当通过应用程序调试步进时,我看到isAnonymous()首先评估,然后isFullyAuthenticated()导致授予访问权限并立即再次拒绝访问.

chz*_*gla 15

感谢您的所有回复.然而答案是完全不同的:)

我把它放在这里以防其他人有同样的问题.

我在带@InitBinder注释的方法中注册了自定义验证器.在控制器上请求的方法调用之后调用此绑定方法.由于此绑定方法未注释@PreAuthorize,请求被拒绝.

解决方案是注释绑定方法,如下所示:

@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
    binder.setValidator(validator);
}
Run Code Online (Sandbox Code Playgroud)

然后,我的OP调用的方法调用就像预期的那样.


Ral*_*lph 5

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

PrePostAnnotationSecurityMetadataSource Java Doc:

可以在类或方法上指定注释,并且特定于方法的注释优先.

这种逻辑的具体实现是在findAnnotation类的方法中完成的PrePostAnnotationSecurityMetadataSource.(不幸的是这种方法是私密的.)

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

但最后一个警告:结束:困难的任务不是重写方法,困难的任务是将"注入"新MethodSecurityMetadataSource的安全系统.我相信你无法使用spring安全命名空间配置,所以你需要通过显式bean声明替换spring安全命名空间.