Spring MVC(或 Spring Boot)。针对安全相关异常的自定义 JSON 响应,例如 401 Unauthorized 或 403 Forbidden)

2024-02-27

我正在开发 REST 服务。它使用 JSON,并且必须返回一些预定义的 JSON 对象,以防出现问题。默认的 Spring 响应如下所示:

{
  "timestamp": 1512578593776,
  "status": 403,
  "error": "Forbidden",
  "message": "Access Denied",
  "path": "/swagger-ui.html"
}

我想用自己的 JSON 替换这个默认 JSON(带有堆栈跟踪和其他异常相关信息)。

Spring 提供了一种覆盖默认行为的便捷方法。人们应该定义一个@RestControllerAdvice具有自定义异常处理程序的 bean。像这样

@RestControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(value = {Exception.class})
  public ResponseEntity<ExceptionResponse> unknownException(Exception ex) {
    ExceptionResponse resp = new ExceptionResponse(ex, level); // my custom response object
    return new ResponseEntity<ExceptionResponse>(resp, resp.getStatus());
  }
  @ExceptionHandler(value = {AuthenticationException.class})
  public ResponseEntity<ExceptionResponse> authenticationException(AuthenticationExceptionex) {
      // WON'T WORK
  }
}

习俗ExceptionResponse然后 Spring 使用特殊的消息转换器将对象转换为 JSON。

问题是,安全异常如InsufficientAuthenticationException不能被注释为的方法拦截@ExceptionHandler。这种异常发生在 Spring MVC 调度程序 servlet 进入并且所有 MVC 处理程序初始化之前。

可以使用自定义过滤器拦截此异常并从头开始构建自己的 JSON 序列化。在这种情况下,人们将获得完全独立于 Spring MVC 基础设施其余部分的代码。这不好。

我找到的解决方案似乎有效,但看起来很疯狂。

@Configuration
public class CustomSecurityConfiguration extends 
WebSecurityConfigurerAdapter {

@Autowired
protected RequestMappingHandlerAdapter requestMappingHandlerAdapter;

@Autowired
protected GlobalExceptionHandler exceptionHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .anyRequest()
        .fullyAuthenticated();

    http.exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint());
}

public AuthenticationEntryPoint authenticationEntryPoint() {
    return new AuthenticationEntryPoint() {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException authException) throws IOException, ServletException {

            try {
                ResponseEntity<ExceptionResponse> objResponse = exceptionHandler.authenticationException(authException);

                Method unknownException = exceptionHandler.getClass().getMethod("authenticationException", AuthenticationException.class);

                HandlerMethod handlerMethod = new HandlerMethod(exceptionHandler, unknownException);

                MethodParameter returnType = handlerMethod.getReturnValueType(objResponse);

                ModelAndViewContainer mvc = new ModelAndViewContainer(); // not really used here.

                List<HttpMessageConverter<?>> mconverters = requestMappingHandlerAdapter.getMessageConverters();

                DispatcherServletWebRequest webRequest = new DispatcherServletWebRequest(request, response);

                HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor(mconverters);

                processor.handleReturnValue(objResponse, returnType, mvc, webRequest);
            } catch (IOException e) {
                throw e;
            } catch (RuntimeException e) {
                throw e;                    
            } catch (Exception e) {
                throw new ServletException(e);
            }
        }
    };
}

有没有一种方法可以使用 Spring 序列化管道(在消息转换器中使用 Spring 构建、MIME 格式协商等),它看起来比这更好?


创建Bean类

@Component public class AuthenticationExceptionHandler implements AuthenticationEntryPoint, Serializable

并覆盖commence() method并使用对象映射器创建一个 json 响应,如下例所示

 ObjectMapper mapper = new ObjectMapper();
 String responseMsg = mapper.writeValueAsString(responseObject);
 response.getWriter().write(responseMsg);

and @Autowire AuthenticationExceptionHandler in SecurityConfiguration班级和在configure(HttpSecurity http) method添加以下行

        http.exceptionHandling()
            .authenticationEntryPoint(authenticationExceptionHandler) 

这样,您应该能够发送自定义 json 响应 401 /403。与上面相同,您可以使用AccessDeniedHandler。请告诉我们这是否帮助您解决了问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring MVC(或 Spring Boot)。针对安全相关异常的自定义 JSON 响应,例如 401 Unauthorized 或 403 Forbidden) 的相关文章

随机推荐

  • Xcode:UI 自动化:waitForValid()

    有一个 waitForInvalid 但 waitForValid 函数呢 由于某种原因 push popTimeout 在很多情况下对我不起作用 苹果 如果元素是 有效 但不是 可见 则可能返回得太早 这应该等到其可见且有效 UIATar
  • Firestore 添加文档 ||离线||回调[重复]

    这个问题在这里已经有答案了 期间未收到在集合中添加文档的回调offline 它在在线模式下运行良好 但是 文档正在被添加 并且侦听集合的侦听器正在被添加document快照 let database Firestore firestore
  • 带有外部第三方 jar 的 Eclipse 插件

    我有一个 RCP 应用程序 其中包含不同的插件 在其中一个插件中 我使用外部第三方 jar 由于版权原因 我无法将该 jar 捆绑到我的产品中 所以我尝试在运行时将 jar 作为外部 jar 包含在内 我所做的如下 在插件manifest
  • 为什么mysql无法创建新用户?

    mysql gt select user host from mysql user user host root 127 0 0 1 root 1 debian sys maint localhost developer localhost
  • 使用 QT 读取 Linux/Ubuntu 上的电池状态

    我目前正在使用 qt 开发一个应用程序 目标是运行 ubuntu 14 04 的平板电脑 由于设备上的电池指示器很差 并且应用程序将长时间全屏运行 因此我想在应用程序内显示电池指示器 搜索发现主要是旧结果或对 windows android
  • 找不到元素“context:annotation-config”的声明

    每当我写作时 春天
  • Highcharts,使 y 轴从零开始

    我想这对某些人来说应该是理所当然的 但我在那些可怕的自动生成的文档中找不到它 您应该在图表对象中添加 yAxis 属性min 0这是一个类似的问题 如何设置 Highcharts 图表最大 y 轴值 https stackoverflow
  • 让Git在分支之间保留不同的section内容

    我正在开发一个用户脚本 我的雇主要求我开始通过 Git 进行管理 现在 我有一个稳定文件和一个测试版文件 以便组织中的每个人都可以安装稳定代码 但如果愿意 可以选择帮助测试测试版添加内容 该文件的某些部分应保持不同 内容和更改不应在分支之间
  • 使用 pandoc ruby​​ 将 HTML 和内联 Mathjax 数学转换为 LaTeX

    我正在构建一个Rails应用程序 并且正在寻找一种方法将带有html和内联MathJax数学 TeX 的数据库条目转换为LaTeX以创建pdf 我发现了和我类似的问题 使用 pandoc 将 html mathjax 转换为 Markdow
  • 这个==- JavaScript 运算符是什么?

    当我发现时 我跌跌撞撞地尝试不同的条件 or 在 JS 控制台中 您可以编写 var a 那么以下是正确的 a 但这是错误的 a 然而 如果你说 a or a 那么这是什么俏皮的东西 操作员 他们不是不同的运营商 Writing a 被解析
  • 使用 XAMPP 包在本地显示 php 站点时出现问题。站点在远程服务器上运行良好

    我在 stackoverflow com 上发表的第一篇文章 一个很棒的网站 我希望我的帖子能为他人的利益做出贡献 情况 我受委托翻新一处really小型 现有 php 驱动的网站 于是 我开始搭建我的环境 Dreamweaver 已安装
  • Selenium 使用 Firefox 配置文件

    我尝试在 Windows 10 系统上使用 Selenium Webdriver 和 Python 来实现浏览器操作的一些自动化 但我有这个问题 Selenium 启动的 Firefox 窗口没有 看到 我已经登录 并且目标站点将我发送到登
  • R 闪亮销毁观察事件

    我是 R Shiny 的新手 我正在尝试创建一个带有一些动态生成的按钮的应用程序 每个按钮都有一个与之关联的observeEvent 我想添加一个重置按钮来删除所有observeEvents 我浏览了一些链接 发现 destroy 函数可以
  • ASP.NET MVC3 中的 HtmlHelper 使用 Action 作为模板:Razor 语法?

    首先我要说的是 也许有更好的方法可以做到这一点 而 Razor 正在为我们指明道路 无论如何 我有一个 HTML 帮助器 它充当某种重复器 但在任意次数的重复之后 它会插入一个备用模板 最明显的用途 在 x 个单元格之后开始新行的表格 助手
  • HTML、jQuery:将一个元素的宽度绑定到另一个元素

    我想将第一个元素 foo 的宽度绑定到第二个元素 bar 的宽度 我希望当元素 bar 的宽度更改时 元素 foo 的宽度自动更改 我知道我可以将元素 foo 的宽度设置为元素 bar 的宽度 正如我们在下面的代码中看到的那样 但这是一次性
  • Visual Basic 2008 中的集合初始化语法?

    我试图确定 Visual Basic 2008 如果重要的话 是 Express 版本 中是否有一种方法可以像 JavaScript 或 Python 那样进行内联集合初始化 Dim oMapping As Dictionary Of In
  • 检测和存储 Web 应用程序客户端所在时区的最佳方法是什么?

    我有一个多时区 Web 应用程序 它将所有 UTC 日期时间值存储在数据库中 当服务器上发生操作时 我可以轻松地将时间转换为 UTC 但是 当客户端输入时间或时间跨度时 检测和存储它的最佳方法是什么 我目前正在做以下事情 获取 Date g
  • 程序执行期间Apache-Spark出现超时异常

    我正在 MAC 中运行 Bash 脚本 该脚本多次调用用Scala语言编写的spark方法 我目前正在尝试使用 for 循环调用此 Spark 方法 100 000 次 在运行少量迭代 大约 3000 次迭代 后 代码退出并出现以下异常 o
  • 在 Jenkins 上构建多项目 Gradle

    我有一个在 Mercurial 存储库中托管的 Gradle 多项目 我想以这样的方式设置我的 Jenkins 如果我只将更改提交到 1 个子项目 那么只有该子项目将被构建并发布到我的 Nexus 存储库 有人可以给我提示吗 或者说这完全有
  • Spring MVC(或 Spring Boot)。针对安全相关异常的自定义 JSON 响应,例如 401 Unauthorized 或 403 Forbidden)

    我正在开发 REST 服务 它使用 JSON 并且必须返回一些预定义的 JSON 对象 以防出现问题 默认的 Spring 响应如下所示 timestamp 1512578593776 status 403 error Forbidden