Spring中的过滤器实际生产中的应用

过滤器的实际用途

过滤器主要用于拦截和处理 HTTP 请求和响应。它在 Web 开发中有许多实际用途,以下是一些常见场景和源码例子:


1. 安全性

用途:

  • 检查用户是否登录(身份认证)。

  • 验证用户的权限(权限校验)。

  • 防范常见的安全攻击(如 SQL 注入、XSS)。

示例代码:验证用户是否登录

@WebFilter(urlPatterns = "/secure/*")
public class AuthFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
​
        // 检查用户是否已登录
        Object user = httpRequest.getSession().getAttribute("user");
        if (user == null) {
            httpResponse.sendRedirect("/login"); // 未登录则跳转到登录页面
            return;
        }
​
        chain.doFilter(request, response); // 已登录则继续执行请求
    }
}

实际用途:

  • 在企业级应用中,保护 /admin/*/secure/* 路径,确保只有已登录用户能访问。


2. 日志记录

用途:

  • 记录请求的访问路径、参数、IP 地址、处理时间。

  • 提供系统的运行日志,用于调试和性能分析。

示例代码:记录请求和响应日志

@WebFilter(urlPatterns = "/*")
public class LoggingFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
​
        long startTime = System.currentTimeMillis();
        System.out.println("Request URL: " + httpRequest.getRequestURI());
        System.out.println("Client IP: " + httpRequest.getRemoteAddr());
​
        chain.doFilter(request, response); // 执行下一个过滤器或目标资源
​
        long duration = System.currentTimeMillis() - startTime;
        System.out.println("Request processed in " + duration + " ms");
    }
}

实际用途:

  • 分析系统的性能瓶颈。

  • 追踪特定用户的行为,便于审计。


3. 数据压缩

用途:

  • 对响应内容进行压缩,减少网络传输的大小,提高响应速度。

示例代码:使用 GZIP 压缩响应

@WebFilter(urlPatterns = "/*")
public class GzipFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
​
        // 包装响应流,进行 GZIP 压缩
        GzipResponseWrapper wrappedResponse = new GzipResponseWrapper(httpResponse);
        chain.doFilter(request, wrappedResponse);
        wrappedResponse.finish();
    }
}
​
// 自定义 GzipResponseWrapper
class GzipResponseWrapper extends HttpServletResponseWrapper {
    private GZIPOutputStream gzipOutputStream;
    private ServletOutputStream outputStream;
​
    public GzipResponseWrapper(HttpServletResponse response) throws IOException {
        super(response);
    }
​
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (outputStream == null) {
            gzipOutputStream = new GZIPOutputStream(getResponse().getOutputStream());
            outputStream = new ServletOutputStream() {
                @Override
                public void write(int b) throws IOException {
                    gzipOutputStream.write(b);
                }
​
                @Override
                public void close() throws IOException {
                    gzipOutputStream.close();
                }
​
                @Override
                public boolean isReady() {
                    return true;
                }
​
                @Override
                public void setWriteListener(WriteListener writeListener) {
                }
            };
        }
        return outputStream;
    }
​
    public void finish() throws IOException {
        if (gzipOutputStream != null) {
            gzipOutputStream.finish();
        }
    }
}
实际用途:
  • 对静态资源(如 HTML、CSS、JavaScript)和 API 响应进行压缩,优化带宽使用。


4. 跨域请求处理

用途:

  • 设置 CORS(跨域资源共享)头,允许前端跨域访问后端服务。

示例代码:CORS 过滤器

@WebFilter(urlPatterns = "/*")
public class CorsFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
​
        // 设置 CORS 响应头
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
​
        chain.doFilter(request, response);
    }
}

实际用途:

  • 用于前后端分离项目中,解决跨域访问的问题。


5. 统一编码处理

用途:

  • 统一设置请求和响应的字符编码,防止中文乱码。

示例代码:统一字符编码

@WebFilter(urlPatterns = "/*")
public class EncodingFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }
}

实际用途:

  • 在国际化应用中,确保字符编码一致。


6. 请求限流

用途:

  • 限制特定时间窗口内的请求次数,防止流量攻击。

示例代码:简单的限流逻辑

@WebFilter(urlPatterns = "/*")
public class RateLimitingFilter implements Filter {
​
    private final Map<String, Integer> requestCounts = new HashMap<>();
    private final int LIMIT = 10; // 每分钟限制 10 次请求
​
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
​
        String clientIP = httpRequest.getRemoteAddr();
        requestCounts.putIfAbsent(clientIP, 0);
        int requests = requestCounts.get(clientIP);
​
        if (requests >= LIMIT) {
            httpResponse.setStatus(429); // Too Many Requests
            httpResponse.getWriter().write("Too many requests. Please try again later.");
            return;
        }
​
        requestCounts.put(clientIP, requests + 1);
        chain.doFilter(request, response);
    }
}
实际用途:
  • 防止恶意用户或爬虫频繁访问接口。


总结

过滤器的作用是对请求和响应进行统一的、通用的处理。通过灵活的实现,可以在以下方面提供关键支持:

  1. 安全性(身份认证、权限校验)。

  2. 性能优化(日志记录、请求压缩)。

  3. 前后端协作(跨域处理)。

  4. 国际化支持(字符编码)。

  5. 流量控制(限流)。

通过以上示例代码,您可以根据业务需求,扩展过滤器的功能,实现高效、安全的 Web 应用。

posted @ 2024-11-26 10:54  luorx  阅读(72)  评论(0)    收藏  举报