• 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

    1. package com.itheima.web;
    2. import com.itheima.pojo.User;
    3. import com.itheima.service.UserService;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.*;
    7. import java.io.IOException;
    8. @WebServlet("/loginServlet")
    9. public class LoginServlet extends HttpServlet {
    10. @Override
    11. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    12. // 1、接收客户端用户名和密码
    13. String username =request.getParameter("username");
    14. String password =request.getParameter("password");
    15. // 获取复选框数据
    16. String remember =request.getParameter("remember");
    17. // 2、调用service层进行查询
    18. UserService userService =new UserService();
    19. User user =userService.login(username,password);
    20. // 3、判断查询是否有结果
    21. if (user != null){
    22. // 判断user不为null说明登录成功了
    23. // 判断用户是否勾选了记住我 remember
    24. // 这里用:"1".equals(remember) 而不用remember.equals("1")
    25. // 是为了防止空指针异常 因为remember有可能用户没勾选 为null 然后比较的话会空指针
    26. if ("1".equals(remember)){
    27. // 勾选了,发送Cookie
    28. // 1 创建Cookie对象
    29. Cookie c_username =new Cookie("username",username);
    30. Cookie c_password =new Cookie("password",password);
    31. // 设置Cookie数据在客户端存活的时间
    32. c_username.setMaxAge(60*60*24*60);
    33. c_password.setMaxAge(60*60*24*60);
    34. // 2 发送Cookie
    35. response.addCookie(c_username);
    36. response.addCookie(c_password);
    37. }
    38. // 2. 把user查询出来的数据先封装到Session域当中 (数据保存在了服务器之间共享)
    39. HttpSession httpSession =request.getSession();
    40. // 存储到Session域中
    41. httpSession.setAttribute("user",user);
    42. // 1.登录成功 (要求:动态重定向到MVC三层架构讲的商品增删改查操作:SelectAllServlet资源下查询所有)
    43. String path =request.getContextPath();
    44. response.sendRedirect(path+"/selectAllServlet");
    45. } else {
    46. // 登录失败
    47. // 储存错误提示信息到request域当中 转发给login.jsp
    48. request.setAttribute("login_msg","用户名或密码错误");
    49. // 跳转到登录的login.jsp页面
    50. request.getRequestDispatcher("/login.jsp").forward(request,response);
    51. }
    52. }
    53. @Override
    54. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    55. this.doGet(request, response);
    56. }
    57. }

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

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

     拦截器:

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

    1. package com.itheima.web.filter;
    2. import javax.servlet.*;
    3. import javax.servlet.annotation.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpSession;
    6. import java.io.IOException;
    7. /**
    8. * 登陆验证的过滤器
    9. */
    10. @WebFilter("/*")
    11. public class LoginFilter implements Filter {
    12. @Override
    13. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    14. // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)
    15. HttpServletRequest req =(HttpServletRequest) request;
    16. // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
    17. // Filter包下的request转换成HttpServletRequest包下的request
    18. HttpSession session =req.getSession();
    19. Object user =session.getAttribute("user");
    20. // 判断user是否为null
    21. if (user != null){
    22. // 不为null,说明用户登录过了
    23. // 放行
    24. chain.doFilter(request, response);
    25. }
    26. else {
    27. // 为null,说明用户未登录 (跳转到登录页面)
    28. request.setAttribute("login_msg","您尚未登陆!");
    29. request.getRequestDispatcher("/login.jsp").forward(req,response);
    30. }
    31. }
    32. public void init(FilterConfig config) throws ServletException {
    33. }
    34. public void destroy() {
    35. }
    36. }

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

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

    1. package com.itheima.web.filter;
    2. import javax.servlet.*;
    3. import javax.servlet.annotation.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpSession;
    6. import java.io.IOException;
    7. /**
    8. * 登陆验证的过滤器
    9. */
    10. @WebFilter("/*")
    11. public class LoginFilter implements Filter {
    12. @Override
    13. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    14. HttpServletRequest req =(HttpServletRequest) request;
    15. // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
    16. // Filter包下的request转换成HttpServletRequest包下的request
    17. // !判断访问资源路径是否和登录注册有关
    18. String[] urls = {"/login.jsp","/register.jsp","/imgs/","/css/","/loginServlet","/registerServlet","/checkCodeServlet"};
    19. // ! 获取当前访问的资源路径
    20. String url =req.getRequestURL().toString(); // http://localhost:8089/brand-demo/register.jsp 类型
    21. // ! 判断
    22. for (String u:urls) { // 遍历urls数组里面地址
    23. if (url.contains(u)){ // 如果url包含遍历出来的u
    24. // 包含的话 说明用户访问的是登录或者注册相关的资源路径
    25. // 放行即可
    26. chain.doFilter(request, response);
    27. return;
    28. }
    29. }
    30. // (5个就依次判断就可以了 判断完发现不包含就继续往下执行代码了)
    31. // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)
    32. HttpSession session =req.getSession();
    33. Object user =session.getAttribute("user");
    34. // 判断user是否为null
    35. if (user != null){
    36. // 不为null,说明用户登录过了
    37. // 放行
    38. chain.doFilter(request, response);
    39. }
    40. else {
    41. // 为null,说明用户未登录 (跳转到登录页面)
    42. request.setAttribute("login_msg","您尚未登陆!");
    43. request.getRequestDispatcher("/login.jsp").forward(req,response);
    44. }
    45. }
    46. public void init(FilterConfig config) throws ServletException {
    47. }
    48. public void destroy() {
    49. }
    50. }

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

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

    拦截器代码:

    1. package com.itheima.web.filter;
    2. import javax.servlet.*;
    3. import javax.servlet.annotation.*;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpSession;
    6. import java.io.IOException;
    7. /**
    8. * 登陆验证的过滤器
    9. */
    10. @WebFilter("/*")
    11. public class LoginFilter implements Filter {
    12. @Override
    13. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    14. HttpServletRequest req =(HttpServletRequest) request;
    15. // 注意:Session中的调用getSession()方法的request是HttpServletRequest包下的request所以需要把
    16. // Filter包下的request转换成HttpServletRequest包下的request
    17. // !判断访问资源路径是否和登录注册有关
    18. String[] urls = {"/login.jsp","/register.jsp","/imgs/","/css/","/loginServlet","/registerServlet","/checkCodeServlet"};
    19. // ! 获取当前访问的资源路径
    20. String url =req.getRequestURL().toString(); // http://localhost:8089/brand-demo/register.jsp 类型
    21. // ! 判断
    22. for (String u:urls) { // 遍历urls数组里面地址
    23. if (url.contains(u)){ // 如果url包含遍历出来的u
    24. // 包含的话 说明用户访问的是登录或者注册相关的资源路径
    25. // 放行即可
    26. chain.doFilter(request, response);
    27. return; // 结束代码了 下面的代码也不执行了
    28. }
    29. }
    30. // (5个就依次判断就可以了 判断完发现不包含就继续往下执行代码了)
    31. // 1.判断Session中是否有user (LoginServlet登录中查询出来存储在Session域中的用户信息)
    32. HttpSession session =req.getSession();
    33. Object user =session.getAttribute("user");
    34. // 判断user是否为null
    35. if (user != null){
    36. // 不为null,说明用户登录过了
    37. // 放行
    38. chain.doFilter(request, response);
    39. }
    40. else {
    41. // 为null,说明用户未登录 (跳转到登录页面)
    42. request.setAttribute("login_msg","您尚未登陆!");
    43. request.getRequestDispatcher("/login.jsp").forward(req,response);
    44. }
    45. }
    46. public void init(FilterConfig config) throws ServletException {
    47. }
    48. public void destroy() {
    49. }
    50. }

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

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

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

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

    1. package com.itheima.web;
    2. import com.itheima.pojo.User;
    3. import com.itheima.service.UserService;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.*;
    7. import java.io.IOException;
    8. @WebServlet("/loginServlet")
    9. public class LoginServlet extends HttpServlet {
    10. @Override
    11. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    12. // 1、接收客户端用户名和密码
    13. String username =request.getParameter("username");
    14. String password =request.getParameter("password");
    15. // 获取复选框数据
    16. String remember =request.getParameter("remember");
    17. // 2、调用service层进行查询
    18. UserService userService =new UserService();
    19. User user =userService.login(username,password);
    20. // 3、判断查询是否有结果
    21. if (user != null){
    22. // 判断user不为null说明登录成功了
    23. // 判断用户是否勾选了记住我 remember
    24. // 这里用:"1".equals(remember) 而不用remember.equals("1")
    25. // 是为了防止空指针异常 因为remember有可能用户没勾选 为null 然后比较的话会空指针
    26. if ("1".equals(remember)){
    27. // 勾选了,发送Cookie
    28. // 1 创建Cookie对象
    29. Cookie c_username =new Cookie("username",username);
    30. Cookie c_password =new Cookie("password",password);
    31. // 设置Cookie数据在客户端存活的时间
    32. c_username.setMaxAge(60*60*24*60);
    33. c_password.setMaxAge(60*60*24*60);
    34. // 2 发送Cookie
    35. response.addCookie(c_username);
    36. response.addCookie(c_password);
    37. }
    38. // 2. 把user查询出来的数据先封装到Session域当中 (数据保存在了服务器之间共享)
    39. HttpSession httpSession =request.getSession();
    40. // 存储到Session域中
    41. httpSession.setAttribute("user",user);
    42. // 1.登录成功 (要求:动态重定向到MVC三层架构讲的商品增删改查操作:SelectAllServlet资源下查询所有)
    43. String path =request.getContextPath();
    44. response.sendRedirect(path+"/selectAllServlet");
    45. } else {
    46. // 登录失败
    47. // 储存错误提示信息到request域当中 转发给login.jsp
    48. request.setAttribute("login_msg","用户名或密码错误");
    49. // 跳转到登录的login.jsp页面
    50. request.getRequestDispatcher("/login.jsp").forward(request,response);
    51. }
    52. }
    53. @Override
    54. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    55. this.doGet(request, response);
    56. }
    57. }

    login.jsp:

    1. <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
    2. <!DOCTYPE html>
    3. <html lang="en">
    4. <head>
    5. <meta charset="UTF-8">
    6. <title>login</title>
    7. <link href="css/login.css" rel="stylesheet">
    8. </head>
    9. <body>
    10. <div id="loginDiv" style="height: 350px">
    11. <form action="/brand-demo/loginServlet" id="form">
    12. <h1 id="loginMsg">LOGIN IN</h1>
    13. <div id="errorMsg">${login_msg} ${register_msg}</div>
    14. <%--
    15. ${login_msg} 就是我们在LoginServlet资源下登录失败后转发到login页面把
    16. 登录页面展示给用户,并且把转发时储存到request域当中的数据(用户名或密码错误)拿
    17. 到展示在登录页面上 ${login_msg}:EL表达式 拿储存在域中数据的
    18. ${register_msg} 拿到的是RegisterServlet资源下封装到request域当中的数据通过转发过来
    19. (注册成功,请登录)展示在登录的页面上
    20. --%>
    21. <p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>
    22. <p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>
    23. <%-- value 的作用就是在复选框中,假设选中了该复选框那么该复选框的值也就是该value的值
    24. 这里remember是复选框 当我们勾选后 该默认值为“1”
    25. --%>
    26. <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p>
    27. <div id="subDiv">
    28. <input type="submit" class="button" value="login up">
    29. <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
    30. <a href="register.jsp">没有账号?</a>
    31. </div>
    32. </form>
    33. </div>
    34. </body>
    35. </html>

     

  • 相关阅读:
    !=和!==的区别
    【Java SE】封装的详解
    MySQL——连接查询与子查询
    水题: 旋转数组系列
    Vue2+Element-ui实现el-table表格自适应高度
    学习SDN开发工具
    python爬虫-32-python字体反爬,网页看到的和实际下载的不一致(理论)
    什么是jvm
    开源项目在线化 中文繁简体转换/敏感词/拼音/分词/汉字相似度/markdown 目录
    高级词汇和句子(二)-day15
  • 原文地址:https://blog.csdn.net/lwj_07/article/details/125469384