Rest 使用@PreAuthorize时从Spring控制器返回405 vs 403

Rest 使用@PreAuthorize时从Spring控制器返回405 vs 403,rest,spring-security,annotations,Rest,Spring Security,Annotations,我们最近开始对REST端点使用@PreAuthorize注释。它工作得很好,但是,我确实有一个关于发出GET与POST或PUT时返回的HTTP代码的问题。 似乎当用户未被授权访问控制器的REST端点时,GET和PUT/POST返回的HTTP状态不同 例如,如果我有一个端点是GET,并且有一个@PreAuthorize注释,而用户没有访问权限,那么将返回一个403禁止。这就是我所期望的 如果相同的注释随后放置在POST或PUT的控制器方法上,则HTTP响应是405方法不允许的(请注意,正确授权后,

我们最近开始对REST端点使用
@PreAuthorize
注释。它工作得很好,但是,我确实有一个关于发出GET与POST或PUT时返回的HTTP代码的问题。 似乎当用户未被授权访问控制器的REST端点时,GET和PUT/POST返回的HTTP状态不同

例如,如果我有一个端点是GET,并且有一个
@PreAuthorize
注释,而用户没有访问权限,那么将返回一个403禁止。这就是我所期望的

如果相同的注释随后放置在POST或PUT的控制器方法上,则HTTP响应是405方法不允许的(请注意,正确授权后,POST/PUT方法将按预期返回200)

单步执行代码时,您可以看到底层安全筛选器返回403,但在POST/PUT场景中,状态代码被删除/忽略并替换为405,这与控制器代码中出现
NullPointerException
时的情况非常相似


这是预期的行为,还是应该始终为无法访问端点的用户返回403禁止?

请求之间的某个位置可能正在进行内部重定向,并最终到达一个端点,该端点需要不同的HTTP请求类型,因此您将获得HTTP 405。
我发现这是身份验证中最常见的原因

对我来说,问题出在
安全配置中


通过删除行
.and().exceptionHandling().accessDeniedPage(“/access DeniedPage”)
我得到了
403禁止
,而不是
405方法不允许
,这很可能是您所期望的。

我通过在错误控制器中允许额外的HTTP方法解决了这个问题,与只允许GET请求不同:

public class MyErrorController implements ErrorController {
    @RequestMapping(method = {
            RequestMethod.GET,
            RequestMethod.HEAD,
            RequestMethod.POST,
            RequestMethod.PUT,
            RequestMethod.DELETE,
            RequestMethod.OPTIONS,
            RequestMethod.TRACE,
            RequestMethod.PATCH})
    public String displayError(){
        // display error
    }
}
我的解释是:

  • 请求的资源允许使用POST方法,但SpringSecurity由于身份验证或授权无效而拒绝请求
  • SpringSecurity在内部重定向到错误控制器,以显示HTTP 403的错误页面。这里使用来自初始请求的HTTP方法,即POST
  • 错误控制器只允许GET请求,这就是返回HTTP 405的原因

  • 在我看来,405是由@PreAuthorize注释抛出的,而不是访问控制层抛出的。尝试对包org.springframework.security启用调试级别,以了解其实际情况。我认为您的请求方法类型不正确。您知道为什么指定自定义拒绝访问页面会改变行为吗?我没有对此进行调查,抱歉