Spring Boot中实现全局Token验证的两种方式总结

 更新时间:2025年05月23日 10:29:11   作者:和烨  
这篇文章主要给大家介绍了关于Spring Boot中实现全局Token验证的两种方式,文中通过拦截器和过滤器实现全局Token验证,解决接口重复验证问题,对比两者优缺点及适用场景,提供统一异常处理方案,需要的朋友可以参考下

前言

在 Spring Boot 项目中,Token 验证是保护接口安全的常见手段。如果每个接口都单独编写 Token 验证逻辑,会导致代码冗余且难以维护。为了解决这个问题,可以通过 拦截器(Interceptor) 或 过滤器(Filter) 实现全局 Token 验证,从而统一处理所有接口的验证逻辑。

本文将详细介绍如何使用拦截器和过滤器实现全局 Token 验证,并提供完整的代码示例和最佳实践。

一、为什么需要全局 Token 验证?

在前后端分离的架构中,客户端通常通过 Token 进行身份验证。如果每个接口都单独验证 Token,会导致以下问题:

  • 代码冗余:每个接口都需要编写重复的验证逻辑。
  • 维护困难:当验证逻辑需要修改时,需要修改所有相关接口。
  • 容易遗漏:新增接口时可能会忘记添加验证逻辑,导致安全漏洞。

通过全局 Token 验证,可以统一处理所有接口的验证逻辑,提高代码的复用性和可维护性。

二、使用拦截器实现全局 Token 验证

拦截器是 Spring MVC 提供的一种机制,可以在请求到达控制器之前或之后执行特定的逻辑。以下是实现步骤:

1. 创建 Token 验证拦截器

创建一个拦截器类,实现 HandlerInterceptor 接口,并在 preHandle 方法中编写 Token 验证逻辑。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头中获取 Token
        String token = request.getHeader("Authorization");

        // 验证 Token
        if (token == null || !isValidToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授权
            response.getWriter().write("Token 无效或未提供");
            return false; // 中断请求
        }

        return true; // 继续执行请求
    }

    // 模拟 Token 验证逻辑
    private boolean isValidToken(String token) {
        // 这里可以调用具体的 Token 验证服务
        return "valid-token".equals(token);
    }
}

2. 注册拦截器

将拦截器注册到 Spring MVC 中,并配置需要拦截的路径。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private TokenInterceptor tokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 拦截所有路径
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**") // 拦截所有接口
                .excludePathPatterns("/login", "/register"); // 排除不需要拦截的路径
    }
}

3. 测试拦截器

启动项目后,访问任意接口时,如果请求头中没有提供有效的 Token,则会返回 401 错误。

三、使用过滤器实现全局 Token 验证

过滤器是 Servlet 提供的一种机制,可以在请求到达 Spring MVC 之前执行逻辑。以下是实现步骤:

1. 创建 Token 验证过滤器

创建一个过滤器类,实现 Filter 接口,并在 doFilter 方法中编写 Token 验证逻辑。

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TokenFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 从请求头中获取 Token
        String token = httpRequest.getHeader("Authorization");

        // 验证 Token
        if (token == null || !isValidToken(token)) {
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 未授权
            httpResponse.getWriter().write("Token 无效或未提供");
            return; // 中断请求
        }

        chain.doFilter(request, response); // 继续执行请求
    }

    // 模拟 Token 验证逻辑
    private boolean isValidToken(String token) {
        // 这里可以调用具体的 Token 验证服务
        return "valid-token".equals(token);
    }
}

2. 注册过滤器

将过滤器注册到 Spring Boot 中,并配置需要拦截的路径。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<TokenFilter> tokenFilter() {
        FilterRegistrationBean<TokenFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TokenFilter());
        registrationBean.addUrlPatterns("/*"); // 拦截所有路径
        registrationBean.setOrder(1); // 设置过滤器顺序
        return registrationBean;
    }
}

3. 测试过滤器

启动项目后,访问任意接口时,如果请求头中没有提供有效的 Token,则会返回 401 错误。

四、拦截器 vs 过滤器

1. 拦截器的优势

  • 与 Spring MVC 深度集成,可以访问 Spring 的上下文和 Bean。
  • 可以精确控制拦截的路径(通过 addPathPatterns 和 excludePathPatterns)。
  • 适合处理与业务逻辑相关的拦截(如权限验证、日志记录)。

2. 过滤器的优势

  • 更底层,可以拦截所有请求(包括静态资源)。
  • 适合处理与 Servlet 相关的逻辑(如编码设置、跨域处理)。

3. 选择建议

  • 如果需要在 Spring MVC 的上下文中处理逻辑(如依赖注入),优先使用拦截器。
  • 如果需要拦截所有请求(包括静态资源),或者需要更底层的控制,优先使用过滤器。

五、全局异常处理

在拦截器或过滤器中,如果验证失败,直接返回错误响应可能会导致客户端无法解析。可以通过全局异常处理机制统一返回 JSON 格式的错误信息。

1. 定义统一响应格式

public class ApiResponse {
    private boolean status;
    private int code;
    private String message;

    // 构造方法和 Getter/Setter 省略
}

2. 全局异常处理器

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UnauthorizedException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ApiResponse handleUnauthorizedException(UnauthorizedException e) {
        return new ApiResponse(false, 401, e.getMessage());
    }
}

3. 在拦截器或过滤器中抛出异常

if (token == null || !isValidToken(token)) {
    throw new UnauthorizedException("Token 无效或未提供");
}

六、总结

通过拦截器或过滤器,可以轻松实现 Spring Boot 项目中所有接口的 Token 验证。以下是两种方式的对比:

特性拦截器(Interceptor)过滤器(Filter)
集成方式Spring MVC 集成Servlet 集成
拦截范围只能拦截 Spring MVC 的请求可以拦截所有请求(包括静态资源)
依赖注入支持不支持
适用场景业务逻辑相关的拦截(如权限验证)底层逻辑相关的拦截(如编码设置)

根据项目需求选择合适的方式,并结合全局异常处理机制,可以构建一个健壮且易维护的 Token 验证系统。

到此这篇关于Spring Boot中实现全局Token验证两种方式的文章就介绍到这了,更多相关SpringBoot全局Token验证方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java分布式事务的 6 种解决方案

    详解Java分布式事务的 6 种解决方案

    在分布式系统、微服务架构大行其道的今天,服务间互相调用出现失败已经成为常态,本文侧重于其他几项,关于 2PC、3PC 传统事务,网上资料已经非常多了,这里不多做重复,本文通过示例给大家介绍Java分布式事务的 6 种解决方案,一起看看吧
    2021-06-06
  • Spring开发中自定义注解的使用详解

    Spring开发中自定义注解的使用详解

    这篇文章主要介绍了Spring开发中自定义注解的使用详解,在Java项目中,可以自定义注解,方便进行某些处理操作,提供开发效率,需要的朋友可以参考下
    2024-01-01
  • Java volatile关键字特性讲解下篇

    Java volatile关键字特性讲解下篇

    JMM要求保证可见性、原子性、有序性,volatile可以保证其中的两个,本篇文章具体验证volatile的可见性,不原子性和禁重排,同时解决volatile的不保证原子性,让代码具有原子性
    2022-12-12
  • Java多线程实现模拟12306火车站售票系统

    Java多线程实现模拟12306火车站售票系统

    12360火车票售票系统基本上大家都用过,那你知道是怎么实现的吗,今天我们就模拟12306火车站售票系统来实现,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 一文详解Java Netty中的Constant类

    一文详解Java Netty中的Constant类

    这篇文章主要介绍了Constants类即常量类是将一些常用的变量集合到一个地方的类,文中有详细的代码示例,感兴趣的同学可以参考一下
    2023-05-05
  • java EasyExcel实现动态列解析和存表

    java EasyExcel实现动态列解析和存表

    这篇文章主要为大家介绍了java EasyExcel实现动态列解析和存表示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • SpringMVC事件监听ApplicationListener实例解析

    SpringMVC事件监听ApplicationListener实例解析

    这篇文章主要介绍了SpringMVC事件监听ApplicationListener实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • java实现汉字转unicode与汉字转16进制实例

    java实现汉字转unicode与汉字转16进制实例

    这篇文章主要介绍了java实现汉字转unicode与汉字转16进制的实现方法,是Java操作汉字编码转换的一个典型应用,非常具有实用价值,需要的朋友可以参考下
    2014-10-10
  • 没有编辑器的环境下是如何创建Servlet(Tomcat+Java)项目的?

    没有编辑器的环境下是如何创建Servlet(Tomcat+Java)项目的?

    今天给大家带来的是关于Java的相关知识,文章围绕着在没有编辑器的环境下如何创建Servlet(Tomcat+Java)项目展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • java中重写equals()方法的同时要重写hashcode()方法(详解)

    java中重写equals()方法的同时要重写hashcode()方法(详解)

    下面小编就为大家带来一篇java中重写equals()方法的同时要重写hashcode()方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论