七的博客

Servlet过滤器的应用场景

Java

Servlet过滤器的应用场景

Servlet 过滤器是 Servlet 规范中定义的一种组件,英文叫做 Filter 。

它可以拦截同时处理 Servlet 的请求和响应。执行顺序如下:

Servlet 拦截器前置处理 > Servlet 接口业务逻辑 > Servlet 后置处理

比如说,你的请求接口需要进行权限校验,普通的用户跟有权限的用户访问接口或者页面会有不同的处理方式,没有权限的用户拒绝访问。

还可以修改请求编码等,如果不设置此编码,收到的请求参数包含中文的话就可能乱码。也可以记录请求的一些参数信息,打印出来请求地址、请求参数等到控制台中。

在处理响应的场景下,可以修改应答的编码,这样客户端收到中文的时候就不会乱码。

总结一下常用的应用场景:

  • 登录验证,通过过滤器检查用户是否登录,未登录的请求可以重定向到登录页面。在做这种管理系统的场景下,权限校验是特别有必要的。

  • 权限控制,根据用户的角色或权限,过滤器去限制用户对某些接口或者资源的访问。

  • 请求编码设置,对于 POST 请求,通过过滤器去设置请求的编码,让后端正确解析请求参数。

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

  • 防止 XSS 攻击,过滤器可以对请求参数进行过滤,移除恶意的脚本代码等,防止 XSS 攻击。安全是一门很复杂的学科,可以通过学习一些 Web 攻防技巧来预防。

下面看一个认证过滤器的写法:

首先新建一个 AuthFilter 类,这个类实现了 javax.servlet.Filter 接口:

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

public class AuthFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

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

        boolean isLoggedIn = (session != null && session.getAttribute("user") != null);

        if (isLoggedIn) {
            // 用户已经登录了,把请求丢给后续的过滤器或者 Servlet。
            chain.doFilter(request, response);
        } else {
            // 用户没有登录,重定向到登录页面
            httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
        }
    }

    @Override
    public void destroy() {
        // 销毁操作
    }
}

同时需要再 web.xml 中进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <filter>
        <filter-name>AuthFilter</filter-name>
        <filter-class>com.suny.AuthFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>AuthFilter</filter-name>
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

</web-app>

在 web.xml 中,定义了一个名为 AuthFilter 的过滤器。

这个过滤器的位置位于 com.suny.AuthFilter,当请求触发这个过滤器的时候会去调用这个类的实例。

然后这个过滤器会拦截所有访问 /admin/* 这种格式的请求。未登录的用户就不让继续操作,已经登录的用户就可以正常操作。

类似的,也可以实现这个过滤器的接口,实现其他的业务校验逻辑或者处理逻辑等。

不过需要注意的几点:

  • 如果有多个过滤器,执行顺序跟 web.xml 中的配置顺序决定,需要合理放置过滤器的顺序,避免冲突。
  • 过滤器会对符合条件的每个请求进行处理,因此过滤器的实现应该尽量简单高效,避免影响性能。
  • 记住要在 web.xml 中进行配置。
  • 过滤器中需要正确调用 chain.doFilter() 传递给后面的 Servlet ,不然就要出现 Bug。