Filter过滤器 &(登录功能拦截例子)

Filter:简单来说就是设立在客户端和服务器之间的一个拦截关卡,当发现客户端请求的资源或者服务器响应给客户端的资源不规范(比如:敏感字符等)就会拦截该资源

还有一个作用就是:可以在拦截关卡这里存放一些权限控制在里面 

 一、Fiter快速入门

注意1:这个实现的Filter是 javax.servlet包下的Filter

注意2:只要Filter的拦截路径是/* 那么客户端访问的路径资源或者服务器响应的资源 都是会先被拦截下来的,然后放不放行看代码

 代码演示:

 eg:当我们没有Filter拦截的时候我们开启服务器访问hello.jsp资源结果如下:(正常访问该资源)

 eg:当我们开启Filter拦截不放行的时候我们开启服务器访问hello.jsp资源结果如下:(假设我们不放行 那么相当于客户端访问hello.jsp的请求就被我们拦截下来了而且我们不放行 那么也就是说获取不到资源了)

注意:不放行直接不用写代码即可  放行需要调用放行方法

 开启服务器客户端访问hello.jsp资源:

会发现拿不到资源数据了,因为客户端的请求被拦截下来了

 eg:当我们开启Filter拦截 放行的时候(也就是说拦截到了客户端的请求但是我们放行了)客户端能获取到相应的路径下资源:

 开启服务器客户端访问hello.jsp资源:

二、Filter 执行流程

用代码演示上图的执行流程:

hello.jsp:

 

 访问hello.jsp的结果:如果输出 1  2  3 说明方形访问完资源后会回到Filter中执行放行后的代码逻辑

三、Filter使用细节  (拦截路径配置 & 过滤器链)

3.1、拦截路径的配置

 3.2、过滤器链

 Filter的优先级:

 

 代码演示过滤器链(看是否按着上面的第一步.第二步.....代码执行的):

FilterDemo (Filter1):

 FilterDemo2 (Fiter2):

hello.jsp:

 开启服务器访问hello.jsp看执行结果说明验证上图成功:

 四、登录验证

 我们已经写过的表现层登录功能:LoginServlet

补充: 用cookie的目的是为了记住用户、用session的目的是为了过滤器的使用

package com.itheima.web;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1、接收客户端用户名和密码
            String username =request.getParameter("username");
            String password =request.getParameter("password");

            // 获取复选框数据
            String remember =request.getParameter("remember");

            // 2、调用service层进行查询
            UserService userService =new UserService();
            User user =userService.login(username,password);

            // 3、判断查询是否有结果
            if (user != null){
                // 判断user不为null说明登录成功了

                // 判断用户是否勾选了记住我 remember
                // 这里用:"1".equals(remember) 而不用remember.equals("1")
                // 是为了防止空指针异常 因为remember有可能用户没勾选 为null 然后比较的话会空指针
                if ("1".equals(remember)){
                    // 勾选了,发送Cookie

                    // 1 创建Cookie对象
                    Cookie c_username =new Cookie("username",username);
                    Cookie c_password =new Cookie("password",password);
                    // 设置Cookie数据在客户端存活的时间
                    c_username.setMaxAge(60*60*24*60);
                    c_password.setMaxAge(60*60*24*60);
                    // 2 发送Cookie
                    response.addCookie(c_username);
                    response.addCookie(c_password);

                }

                // 2. 把user查询出来的数据先封装到Session域当中 (数据保存在了服务器之间共享)
                HttpSession httpSession =request.getSession();
                // 存储到Session域中
                httpSession.setAttribute("user",user);

                // 1.登录成功 (要求:动态重定向到MVC三层架构讲的商品增删改查操作:SelectAllServlet资源下查询所有)
                String path =request.getContextPath();
                response.sendRedirect(path+"/selectAllServlet");

            } else {
                // 登录失败
                // 储存错误提示信息到request域当中 转发给login.jsp
                request.setAttribute("login_msg","用户名或密码错误");
                // 跳转到登录的login.jsp页面
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }

        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }

从代码中可以看出我们在判断user不为null的时候说明用户输入的账户和密码是正确的,登录成功的,那么此时我们又把用户输入的信息user储存到了Session域中

因此我们的拦截器只需要拿到Session域中的user数据判断user数据是否为null 、不为null说明用户登录的信息是正确的 那么我们就放行 让用户访问登录后的资源,如果为null 说明用户压根就输入的账户和密码不正确 那么我们就转发到登录的页面 (注意:第一次的时候拦截器里面拿到的user对象肯定为null,因为当客户端访问路径的时候会先进入拦截器路径下,此时的user对象还没有封装到Session域当中  

 拦截器:

客户端访问想要的资源路径的时候 拦截器路径为/* 所以会先进入拦截器中 因此这就说明了上面的红字问题

package com.itheima.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 *  登陆验证的过滤器
 */

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {

        // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)

        HttpServletRequest req =(HttpServletRequest) request;
        // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
        // Filter包下的request转换成HttpServletRequest包下的request
        HttpSession session =req.getSession();
        Object user =session.getAttribute("user");

        // 判断user是否为null
        if (user != null){
            // 不为null,说明用户登录过了
            // 放行
            chain.doFilter(request, response);
        }
        else {
            // 为null,说明用户未登录 (跳转到登录页面)
            request.setAttribute("login_msg","您尚未登陆!");
            request.getRequestDispatcher("/login.jsp").forward(req,response);
        }
    }




    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}

当我们开启服务器客户端访问资源的时候:

 因此我们需要修改代码,当客户端访问到是登录(注册)页面的时候,把关于登录(注册)页面中的资源(css、html等)展示给用户并且放行不被拦截:

package com.itheima.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 *  登陆验证的过滤器
 */

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req =(HttpServletRequest) request;
        // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
        // Filter包下的request转换成HttpServletRequest包下的request

        // !判断访问资源路径是否和登录注册有关
        String[] urls = {"/login.jsp","/register.jsp","/imgs/","/css/","/loginServlet","/registerServlet","/checkCodeServlet"};
        // ! 获取当前访问的资源路径
        String url =req.getRequestURL().toString(); // http://localhost:8089/brand-demo/register.jsp 类型

        // ! 判断
        for (String u:urls) {   // 遍历urls数组里面地址
            if (url.contains(u)){   // 如果url包含遍历出来的u

                // 包含的话 说明用户访问的是登录或者注册相关的资源路径
                // 放行即可
                chain.doFilter(request, response);
                return;

            }
        }
        // (5个就依次判断就可以了 判断完发现不包含就继续往下执行代码了)


        // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)

        HttpSession session =req.getSession();
        Object user =session.getAttribute("user");

        // 判断user是否为null
        if (user != null){
            // 不为null,说明用户登录过了
            // 放行
            chain.doFilter(request, response);
        }
        else {
            // 为null,说明用户未登录 (跳转到登录页面)
            request.setAttribute("login_msg","您尚未登陆!");
            request.getRequestDispatcher("/login.jsp").forward(req,response);
        }
    }




    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}

=====================代码中的细节逻辑分析===================

特别注意的小细节:转发、重定向等,只要是跳转新的页面的,URL地址栏就会发现变化,那么拦截器就会当成是一次新的访问请求 然后给拦截下来了 最后决定放不放行

拦截器代码:

package com.itheima.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 *  登陆验证的过滤器
 */

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req =(HttpServletRequest) request;
        // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
        // Filter包下的request转换成HttpServletRequest包下的request

        // !判断访问资源路径是否和登录注册有关
        String[] urls = {"/login.jsp","/register.jsp","/imgs/","/css/","/loginServlet","/registerServlet","/checkCodeServlet"};
        // ! 获取当前访问的资源路径
        String url =req.getRequestURL().toString(); // http://localhost:8089/brand-demo/register.jsp 类型

        // ! 判断
        for (String u:urls) {   // 遍历urls数组里面地址
            if (url.contains(u)){   // 如果url包含遍历出来的u

                // 包含的话 说明用户访问的是登录或者注册相关的资源路径
                // 放行即可
                chain.doFilter(request, response);
                return;    // 结束代码了 下面的代码也不执行了

            }
        }
        // (5个就依次判断就可以了 判断完发现不包含就继续往下执行代码了)


        // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)

        HttpSession session =req.getSession();
        Object user =session.getAttribute("user");

        // 判断user是否为null
        if (user != null){
            // 不为null,说明用户登录过了
            // 放行
            chain.doFilter(request, response);
        }
        else {
            // 为null,说明用户未登录 (跳转到登录页面)
            request.setAttribute("login_msg","您尚未登陆!");
            request.getRequestDispatcher("/login.jsp").forward(req,response);
        }
    }




    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}

假设我们开启服务器后访问的是login.jsp路径下的资源:

 我们从拦截器的urls数组里面可以看到,我们放行了login.jsp 并且点击登录后进入的是loginServlet路径下的资源 我们也放行了,

这里有一个细节:就是我们放行进入loginServlet路径资源下后看代码:

我们把用户登录的信息封装成user对象封装到了Session域当中了,此时登录成功的话我们是重定向到selectAllServlet路径下的,注意:重定向的时候我们的URL地址栏就会发现变化,相当于重新访问了,那么就再次会被拦截器当成新的客户端请求拦截请求数据,然后决定放不放行,我们通过循环判断发现selectAllServlet不是我们所包含的对象,那么就会循环完后进入下面的代码判断user是否为null,注意:就是因为我们刚才登录的时候在loginServlet路径下已经把user对象封装在Session域当中了 所以这时候user不为null了 ,我们的代码是放行的, 因此我们就能查看到所有商品的数据了,再在selectAllServlet路径资源下再转发、重定向等新的URL地址时也会放行了,因为user已经有数据了

package com.itheima.web;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1、接收客户端用户名和密码
            String username =request.getParameter("username");
            String password =request.getParameter("password");

            // 获取复选框数据
            String remember =request.getParameter("remember");

            // 2、调用service层进行查询
            UserService userService =new UserService();
            User user =userService.login(username,password);

            // 3、判断查询是否有结果
            if (user != null){
                // 判断user不为null说明登录成功了

                // 判断用户是否勾选了记住我 remember
                // 这里用:"1".equals(remember) 而不用remember.equals("1")
                // 是为了防止空指针异常 因为remember有可能用户没勾选 为null 然后比较的话会空指针
                if ("1".equals(remember)){
                    // 勾选了,发送Cookie

                    // 1 创建Cookie对象
                    Cookie c_username =new Cookie("username",username);
                    Cookie c_password =new Cookie("password",password);
                    // 设置Cookie数据在客户端存活的时间
                    c_username.setMaxAge(60*60*24*60);
                    c_password.setMaxAge(60*60*24*60);
                    // 2 发送Cookie
                    response.addCookie(c_username);
                    response.addCookie(c_password);

                }

                // 2. 把user查询出来的数据先封装到Session域当中 (数据保存在了服务器之间共享)
                HttpSession httpSession =request.getSession();
                // 存储到Session域中
                httpSession.setAttribute("user",user);

                // 1.登录成功 (要求:动态重定向到MVC三层架构讲的商品增删改查操作:SelectAllServlet资源下查询所有)
                String path =request.getContextPath();
                response.sendRedirect(path+"/selectAllServlet");

            } else {
                // 登录失败
                // 储存错误提示信息到request域当中 转发给login.jsp
                request.setAttribute("login_msg","用户名或密码错误");
                // 跳转到登录的login.jsp页面
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }

        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>
<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-demo/loginServlet" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <div id="errorMsg">${login_msg} ${register_msg}</div>
        <%--
        ${login_msg} 就是我们在LoginServlet资源下登录失败后转发到login页面把
        登录页面展示给用户,并且把转发时储存到request域当中的数据(用户名或密码错误)拿
        到展示在登录页面上  ${login_msg}:EL表达式 拿储存在域中数据的

        ${register_msg} 拿到的是RegisterServlet资源下封装到request域当中的数据通过转发过来
        (注册成功,请登录)展示在登录的页面上
        --%>


        <p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>

        <p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>


        <%-- value 的作用就是在复选框中,假设选中了该复选框那么该复选框的值也就是该value的值
                这里remember是复选框 当我们勾选后 该默认值为“1”
        --%>
        <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.jsp">没有账号?</a>
        </div>
    </form>
</div>


</body>

</html>

 

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Filter过滤器Java Web中的一种组件,用于在请求到达Servlet之前或者响应离开Servlet之后对请求和响应进行预处理和后处理。Filter可以用于实现很多功能,例如登录验证、字符编码转换、日志记录等。下面是一个登录功能拦截例子: 1.创建一个实现Filter接口的过滤器类,重写doFilter方法,在该方法中实现登录验证逻辑。 2.在web.xml文件中配置该过滤器,指定需要拦截的URL路径。 3.在登录页面的Servlet中,判断用户是否已经登录,如果已经登录则跳转到主页,否则跳转到登录页面。 4.在主页的Servlet中,判断用户是否已经登录,如果没有登录则跳转到登录页面。 下面是一个简单的登录功能拦截例子: ``` public class LoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; HttpSession session = req.getSession(); String uri = req.getRequestURI(); if (uri.endsWith("login.jsp") || uri.endsWith("login.do")) { chain.doFilter(request, response); } else { String username = (String) session.getAttribute("username"); if (username == null) { resp.sendRedirect("login.jsp"); } else { chain.doFilter(request, response); } } } @Override public void destroy() { } } ``` 在web.xml文件中配置该过滤器: ``` <filter> <filter-name>LoginFilter</filter-name> <filter-class>com.example.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值