前言
在 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验证方式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论