如何自定义@PreAuthorize(“ isAuthenticated()”)返回的http状态?

时间:2019-04-11 06:42:43

标签: spring-boot spring-security

在spring boot控制器中,我正在使用@PreAuthorize("isAuthenticated()")检查用户是否已登录(使用基本身份验证+ JSESSIONID)。
但是,如果用户未登录,即未通过身份验证,则控制器将返回403 Forbidden
根据我对身份验证与授权的了解,401用于身份验证,403用于授权。

根据我的理解,@PreAuthorize()始终检查用户的授权(如名称所示),但是有任何方法可以根据我们传递给它的参数(即isAuthenticated())对其进行自定义在这里?

我知道还有另一种解决方案:在configure(HttpSecurity httpSecurity)中使用基于URL的安全性配置,但是如果我不想这样做,该怎么办。

请提出任何想法。

1 个答案:

答案 0 :(得分:0)

当您使用@Pre/PostAuthorize注释方法 A 时,spring将为该对象创建代理,并且对该方法的每次调用都将通过代理(如果对象在spring上下文中)。

@Pre/PostAuthorize的代理将评估注释中的表达式(此处复杂),如果正确,则将请求父传递给请求方法(传递给真实方法),如果抛出AccessDaniedException 。您也可以在方法 A 中自己抛出此类异常,其效果将相同。这是关于@Pre/PostAuthorize如何在这里不再起作用的一切!

但这还不是故事的结局!

如果AccessDaniedException没有被抑制或重新转换(没有AccessDaniedException的堆栈),那么它将在Spring Security中被ExceptionTranslationFilter捕获,并且ExceptionTranslationFilter将会看到如果用户已已认证

  • 如果不是ExceptionTranslationFilter,则将委托给AccessDeniedHandler来处理这种情况,并且AccessDeniedHandler的默认实现将返回 403 http代码或重定向进入错误页面取决于您是否正在使用休息状态。

  • 如果不是,则ExceptionTranslationFilter将委派给AuthenticationEntryPoint并将处理这种情况(重定向到登录页面,要求提供http basic ...等)。

注意:如果显示ExceptionTranslationFilterAuthenticationException以外的任何其他字符,并且可能显示 500 AccessDeniedException将抛出异常:(

您的问题可能是另一个问题,请查看Spring Security anonymous 401 instead of 403

禁止显示:(:

    @GetMapping(value = "/test/ok")
    public String getOk() {
        try {
            myService.securedMethod();
            return "ok";
        } catch (Exception e) {
            log.info("AccessDeniedException suppressed not rethrowing :(", e);
            return "error";
        }
    }

正确重新翻译:):

    @GetMapping(value = "/test/ok")
    public String getOk() {
        try {
            myService.securedMethod();
            return "ok";
        } catch (AccessDeniedException e) {
            throw new MyException(e); //public MyException(Throwable cause)
        }
    }
相关问题