讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 Spring Security 过滤器中将异常正确返回给前端浏览器

浅晨同学_4857

浅晨同学_4857

发布时间:2026-08-16 18:15:39

|

937人浏览过

|

来源于php中文网

原创

如何在 Spring Security 过滤器中将异常正确返回给前端浏览器

在 Spring Boot + JWT 的 REST 应用中,当 JWT 过期或非法时,过滤器内抛出的异常默认不会被全局异常处理器捕获,需通过 @ResponseStatus 注解声明 HTTP 状态与错误信息,才能确保浏览器收到标准化的 JSON 错误响应。

在 spring boot + jwt 的 rest 应用中,当 jwt 过期或非法时,过滤器内抛出的异常默认不会被全局异常处理器捕获,需通过 `@responsestatus` 注解声明 http 状态与错误信息,才能确保浏览器收到标准化的 json 错误响应。

在基于 Spring Security 的 JWT 认证流程中,JwtTokenFilter 作为 OncePerRequestFilter 在请求进入 Controller 前执行鉴权逻辑。此时若 token 已过期或签名无效,JwtTokenProvider.validateToken() 中抛出的 JwtAuthenticationException 不会自动触发 @ControllerAdvice 或 @ExceptionHandler —— 因为异常发生在 DispatcherServlet 的请求分发之前,全局异常处理器尚未生效。

因此,最简洁、标准且符合 REST 规范的解决方案是:为自定义异常添加 @ResponseStatus 注解,让 Spring MVC 在捕获该异常时自动设置 HTTP 状态码和响应头,并交由默认错误机制(如 BasicErrorController)生成响应体。

✅ 正确做法如下:

  1. 定义带状态码的自定义异常类(推荐放在 exception 包下):
@ResponseStatus(value = HttpStatus.UNAUTHORIZED, reason = "JWT token is expired or invalid!")
public class JwtAuthenticationException extends RuntimeException {
    public JwtAuthenticationException(String message) {
        super(message);
    }
}

⚠️ 注意:HttpStatus.UNAUTHORIZED (401) 比 FORBIDDEN (403) 更语义准确——token 失效属于认证失败(Authentication),而非权限不足(Authorization)。若业务要求区分“未登录”与“登录失效”,也可统一用 401 并在响应体中明确提示。

立即学习“前端免费学习笔记(深入)”;

创意前端视觉设计
创意前端视觉设计

在创建或重塑需要独特视觉方向、应避免通用 AI 生成审美的网站、落地页、仪表盘、UI 组件、海报或应用时使用。

下载
  1. 在过滤器中主动捕获并抛出该异常(关键修改点):

更新 JwtTokenFilter.doFilterInternal(),包裹 jwtTokenProvider.validateToken(token) 及其依赖调用(如 getAuthentication())于 try-catch 中,并显式抛出 JwtAuthenticationException:

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response,
                                FilterChain filterChain) throws ServletException, IOException {
    String token = jwtTokenProvider.resolveToken(request);

    if (token != null) {
        try {
            if (jwtTokenProvider.validateToken(token)) {
                Authentication authentication = jwtTokenProvider.getAuthentication(token);
                if (authentication != null) {
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } else {
                throw new JwtAuthenticationException("JWT token is expired or invalid!");
            }
        } catch (JwtAuthenticationException e) {
            throw e; // 直接抛出,由 Spring 自动处理
        } catch (Exception e) {
            // 捕获其他 JWT 解析异常(如签名错误、格式错误等)
            throw new JwtAuthenticationException("JWT token is expired or invalid!");
        }
    }

    filterChain.doFilter(request, response);
}

✅ 为什么 throw e 即可?因为 @ResponseStatus 已声明该异常应映射为 401 响应;Spring MVC 的 DispatcherServlet 会在整个请求生命周期(包括 Filter 链)中识别并处理此类注解异常,最终调用 DefaultHandlerExceptionResolver 生成标准错误响应(如 {"timestamp":"...","status":401,"error":"Unauthorized","message":"JWT token is expired or invalid!","path":"/api/xxx"})。

  1. (可选但推荐)补充全局异常处理器,统一响应格式:
    若项目已使用 @ControllerAdvice 统一返回 JSON 结构(如 { "code": 401, "message": "...", "data": null }),可额外添加对 JwtAuthenticationException 的处理:
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(JwtAuthenticationException.class)
    public ResponseEntity<ApiResponse<?>> handleJwtException(JwtAuthenticationException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body(ApiResponse.error(401, e.getMessage()));
    }
}

此时需移除 @ResponseStatus(二者不共存),由该处理器完全接管响应逻辑。

? 重要注意事项:

  • 不要在 doFilterInternal 中直接调用 response.sendError() 或手动写入响应体(如 response.getWriter().write(...)),否则会破坏 Spring 的响应生命周期,导致后续 Filter/Interceptor/Controller 无法执行,且可能引发 IllegalStateException: getWriter() has already been called。
  • 确保 JwtAuthenticationException 类不在 @Component 或 @Service 等 Spring 托管范围内,它只是一个 POJO 异常类型,无需注册为 Bean。
  • 若使用 Spring Boot 2.3+,默认启用 server.error.include-message=never(出于安全考虑隐藏错误详情),如需返回 reason 字段,可在 application.yml 中配置:
    server:
      error:
        include-message: always

通过以上改造,当用户携带过期 JWT 访问受保护接口时,浏览器将收到清晰、标准化的 401 Unauthorized 响应及可读错误消息,前端可据此跳转登录页或刷新 Token,真正实现异常从 Filter 到用户的端到端透传。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

更多
python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2823

2023.08.11

前端如何实现即时通讯
前端如何实现即时通讯

实现即时通讯的方法有WebSocket、Long Polling、Server-Sent Events、WebRTC等等。详细介绍:1、WebSocket,它可以在客户端和服务器之间建立持久连接,实现实时的双向通信,前端可以使用 WebSocket API来创建WebSocket连接,并通过发送和接收消息来实现即时通讯;2、Long Polling,是一种模拟实时通信的技术等等。

6143

2023.10.09

前端和后端的区别
前端和后端的区别

前端关注的是用户界面的设计和交互,而后端则注重数据处理和逻辑控制。想了解更多前端后端的相关内容,可以阅读本专题下面的文章。

7090

2024.03.19

php和前端的关联介绍
php和前端的关联介绍

php既可以作为前端语言,也可以作为后端语言。想了解更多php和前端的相关内容,可以阅读本专题下面的文章。

6878

2024.03.22

前端外包工作内容有哪些
前端外包工作内容有哪些

前端外包工作内容包括:1. 网站和应用程序开发;2. 用户界面和交互设计;3. 用户体验优化;4. 设计和视觉开发;5. 跨浏览器兼容性;6. 性能优化;7. 维护和更新;8. 项目管理和沟通。想了解更多前端的相关内容,可以阅读本专题下面的文章。

983

2024.05.22

spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2831

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

517

2026.01.26

Docker Desktop怎么设置端口映射
Docker Desktop怎么设置端口映射

本专题聚焦Docker Desktop容器端口映射与访问配置,整理从创建容器、设置端口绑定到验证本地服务访问的操作流程。针对端口被占用、映射配置错误、容器服务无法访问等情况,也提供相应的检查方向,方便用户完成端口配置。

0

2026.11.03

Docker Desktop镜像构建教程
Docker Desktop镜像构建教程

想使用Docker Desktop将本地项目构建成Docker镜像?本专题围绕镜像构建的实际操作展开,介绍Dockerfile编写、构建命令使用、镜像标签设置和构建日志查看等内容,同时整理镜像无法生成、依赖安装失败及构建缓存异常等问题的排查思路。

0

2026.11.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn