如何在 Spring Boot 中拦截 HTTP 请求响应
Spring 中的拦截器用于在控制器处理客户端请求或响应之前或将响应发送回客户端之前拦截客户端请求或响应。
拦截器是 Spring Web MVC 框架的一部分,提供了一种向应用程序的请求响应生命周期添加预处理/后处理逻辑的方法。
拦截器的实时用例
拦截器的一些常见用例包括任务,例如:
- 日志记录: 拦截器可用于记录 HTTP 请求和响应。这对于调试或跟踪应用程序的性能很有用。
- 安全性: 拦截器可用于执行安全策略。例如,拦截器可用于在允许用户访问资源之前检查用户是否经过身份验证。
- 缓存: 拦截器可用于缓存 HTTP 请求和响应。这可以通过减少需要向底层资源发出请求的次数来提高应用程序的性能。
- 转换: 拦截器可用于转换 HTTP 请求和响应。例如,拦截器可用于将 JSON 请求转换为 XML 响应。
Spring 请求生命周期
在典型的 Spring Boot 应用程序流程中,当客户端向特定端点(URL)发送 HTTP 请求时,该请求首先由 Web 服务器(例如 Apache Tomcat 或 Jetty)接收,然后转发到 Spring Boot 应用程序。
DispatcherServlet 是 Spring Boot 应用程序中传入请求的入口点。一旦 DispatcherServlet 收到请求,它就会查询 HandlerMapping。
HandlerMapping 负责根据控制器中定义的 URL 映射来确定哪个控制器应该处理传入请求。
在 Spring Boot 中创建拦截器
要在 Spring Boot 中创建拦截器,通常需要创建一个实现该HandlerInterceptor
接口的类。
该HandlerInterceptor
接口共有三个方法:
preHandle()
:preHandle()方法是HandlerInterceptor中最重要的方法。该方法在调用实际控制器方法之前执行。它返回一个布尔值,指示请求是否应该继续发送到控制器或停止。postHandle()
:该方法在调用控制器方法之后但在将响应发送到客户端之前执行。它允许您在渲染响应之前修改模型和视图。您可以使用此方法执行处理请求后需要执行的任何任务。例如,您可以使用该postHandle()
方法向响应添加附加信息,或记录响应。afterCompletion()
:该方法在响应发送到客户端后执行。即使在处理请求期间抛出异常,也会调用此方法。它对于清理或资源释放任务很有用。
检查基本身份验证的拦截器
现在让我们创建一个拦截器来执行基本的身份验证检查。仅针对特定端点调用此拦截器/products/new
。在允许访问控制器之前,它将执行基本的身份验证检查。
对于此示例,我们将硬编码用户名和密码来验证用户传递的凭据。
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@Slf4j
public class BasicAuthInterceptor implements HandlerInterceptor {
private static final String USERNAME = "admin";
private static final String PASSWORD = "admin";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("BasicAuthInterceptor::preHandle()");
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Basic ")) {
String base64Credentials = authHeader.substring("Basic ".length());
byte[] decodedCredentials = Base64.getDecoder().decode(base64Credentials);
String credentials = new String(decodedCredentials, StandardCharsets.UTF_8);
String[] parts = credentials.split(":");
String username = parts[0];
String password = parts[1];
if (USERNAME.equals(username) && PASSWORD.equals(password)) {
return true;
}
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("BasicAuthInterceptor::postHandle()");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("BasicAuthInterceptor::afterCompletion()");
}
}
在 Spring Boot 中注册拦截器
创建自定义拦截器后,您需要使用WebMvcConfigurer
配置将其注册到 Spring Boot 应用程序:
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 {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new BasicAuthInterceptor())
.addPathPatterns("/products/new");
}
}
- 点赞
- 收藏
- 关注作者
评论(0)