java - Spring Security - Ajax 调用忽略@ExceptionHandler

标签 java angularjs spring spring-security

我的项目中有一个 Controller 可以处理如下定义的所有异常:

@ControllerAdvice
public class GlobalExceptionHandlingController {

    @ResponseBody
    @ExceptionHandler(value = AccessDeniedException.class)
    public ResponseEntity accessDeniedException() {
        Logger.getLogger("#").log(Level.SEVERE, "Exception caught!");
        return new ResponseEntity("Access is denied", HttpStatus.FORBIDDEN);
    }

}

我在这里关注一个特定的异常,即 Spring Security 在未经授权的请求时抛出的 AccessDeniedException。这适用于“正常”又名非 ajax 请求。我可以单击链接或直接在地址栏中输入 URL,如果请求未经授权,我将看到此消息。

但是在 AJAX 请求(使用 Angular 请求)时,我得到标准的 403 错误页面作为响应,但有趣的是我可以看到 AccessDeniedException 被这个 Controller 捕获了!

我做了一些研究,似乎我需要自定义 AccessDeniedHandler,所以我做了这个:

在我的 Spring Security 配置中添加了这一行:

.and()
.exceptionHandling().accessDeniedPage("/error/403/");

我做了一个特殊的 Controller 来处理这个:

@Controller
public class AjaxErrorController {

    @ResponseBody
    @RequestMapping(value = "/error/403/", method = RequestMethod.GET)
    public ResponseEntity accessDeniedException() {
        return new ResponseEntity("Access is denied (AJAX)", HttpStatus.FORBIDDEN);
    }

}

现在一切正常,但第一个 Controller 仍会捕获异常,但该方法的返回值将被忽略。为什么?

这是应该如何完成的吗?我觉得我在这里遗漏了一些东西。

我正在使用 Spring 4.2.5 和 Spring Security 4.0.4。

最佳答案

虽然我不知道所有细节,但我的理论是它可能是内容类型问题。

通常在进行 AJAX 请求时,期望响应是 JSON 格式,因此浏览器会在请求中添加一个 Accept: application/json header 。

另一方面,您的响应实体:

new ResponseEntity("Access is denied", HttpStatus.FORBIDDEN)

是文本响应,典型的 Spring 设置的默认 Content-Type 是 text/plain

当 Spring 检测到它无法提供客户端所需类型的响应时,它会回退到默认错误页面。

关于java - Spring Security - Ajax 调用忽略@ExceptionHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36789712/

相关文章:

java - Eclipse (C++) 崩溃无法写入核心转储。核心转储已被禁用

javascript - 尝试使用 `directive` 制作图表不起作用

angularjs - 使用 Google 标签管理器时触发 Angular App 的 Google Analytics 网页浏览

java - 如何搜索其他网站的内容并检索结果并放置在我们的 Android 应用程序中?

java - jackson 解码问题

java - 如何在android中的两个子 Activity 之间传输数据?

javascript - 如何在 AngularJS 中将查询字符串与 $location.path() 一起使用

java - 在 Spring MVC 中,在哪里启动和结束计数器来测试速度执行时间?

java - 带有 Spring 数据的 Mongo 集合名称未正确设置

java - 如何创建 "Singleton"Bean 来保存静态 HashMap