Filter过滤器

发布时间 2023-11-10 18:56:07作者: 一往而深,

什么是Filater过滤器

Filter过滤器的基本使用介绍

  • 以权限检查来演示


    但是,只有jsp文件中可以访问session域,那其他的资源,如:html文件,图片该怎样阻止访问呢?

  • Filter过滤器原理

    **注意导入的是javax.servlet包下面的Filter接口

  • 过滤器:AdminFilter

package com.filter;

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

public class AdminFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    //doFilter 方法,专门用于拦截请求。可以做权限检查
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        HttpSession session = httpServletRequest.getSession();
        if(session.getAttribute("user")==null){
            /*请求转发到Login.jsp页面进行登录*/
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;

    }else {
          filterChain.doFilter(servletRequest,servletResponse);
        }

    }

    @Override
    public void destroy() {

    }
}

  • Filter配置信息
 <filter>
        <!--给filter起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置filter的全类名-->
        <filter-class>com.filter.AdminFilter</filter-class>
    </filter>
    <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
    <filter-mapping>
        <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern 配置拦截路径
        / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
/admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
表示admin目录下面所有文件都进行拦截
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

在有些情况下我们的过滤图片可能会失效,这是因为浏览器缓存优化的问题(在前面也遇到过)。即并没有访问服务器而是直接访问了缓存
解决方案

  • 1.清理浏览器的缓存
  • 2.在请求图片资源的时候加上一些没有一样的参数,让浏览器的缓存优化失效
    这实际上让所有指定的资源都可以进行判断session中有没有user以此达到了拦截的效果

完整用户登录和权限检查

在前面的代码中我们只是测试当用户没有登录时,Filter是怎样拦截请求的,而没有测试当用户成功登录时,Filter是怎样放行的。下面将这种情况补充完整

  • login.jsp页面
  • 处理登录的LoginServlet程序
package com.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        final String username = req.getParameter("username");
        final String password = req.getParameter("password");
        //检查用户名和密码是否正确
        if("admin".equals(username)&&"123456".equals(password)){
            //登录成功
            resp.getWriter().write("登录成功");
            req.getSession().setAttribute("user",username);//将用户保持到session中
        }else{
            //登录失败
            //请求转发回到登录页面
           req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }
        }
    }


  • 过滤器程序(没有改变)
package com.filter;

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

public class AdminFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    //doFilter 方法,专门用于拦截请求。可以做权限检查
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        HttpSession session = httpServletRequest.getSession();
        if(session.getAttribute("user")==null){
            /*请求转发到Login.jsp页面进行登录*/
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;

    }else {
            //让程序继续往下走访问用户目标资源(没有这行代码即使登录成功也不会继续访问目标资源)
          filterChain.doFilter(servletRequest,servletResponse);
        }

    }

    @Override
    public void destroy() {

    }
}

这将会达到一个效果,如果直接访问admin目录下面的资源,将会被拦截跳转进入longin.jsp页面。当我们登录成功后(验证登录成功的servlet程序不在拦截范围内),再次访问将将会被放行继续访问目标资源

Filter的生命周期

1.当我们项目启动时将会自动执行构造器和初始化方法,创建出构造器
2.当访问被限制的资源将会执行过滤方法
3.当项目关闭将会执行销毁方法

  • 总结

FilterConfig类的介绍


  • 程序代码
  • 执行结果

FiilterChin多个过滤器执行的细节

FilterChain 过滤器链

  • 过滤器链执行的原理
  • Filter的配置
  • 访问的资源文件
<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/11/10
  Time: 12:31
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入System--%>

<html>
<head>
    <title>资源文件</title>
</head>
<body>
<%
System.out.println("这是resource.jsp文件");
%>
这是资源文件resource.jsp文件
</body>
</html>



我们仅仅是研究过滤器链的执行顺序,所有我们在前置代码(拦截请求)中都对他们进行了放行

验证1:所有过滤器和目标文件都是在同一个线程中





2.多个Filter执行时他们使用的是同一个Request对象(即属于同一个请求)

  • 同一个请求即可以都可以获取到请求参数
  • 同一个请求即可以访问相同的requet域(注意:往request域中存储数据和获取数据的代码需要考虑到过滤器链的执行顺序)

Filter拦截路径的三种匹配方式