过滤器Filter和拦截器Interceptor实现登录校验

过滤器Filter和拦截器Interceptor实现登录校验

码农世界 2024-05-22 前端 62 次浏览 0个评论

一.过滤器

  • Filter过滤器可以把对资源的请求拦截下来,从而实现一些登录验证的功能

    1.Filter的快速入门

    • 1.定义Filter:定义一个类,实现Filter接口,并重写其所有方法。
    • 2.配置
      public class dofilter implements Filter {
          @Override //初始化只执行一次
          public void init(FilterConfig filterConfig) throws ServletException {
              Filter.super.init(filterConfig);
          }
          @Override  //拦截操作
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.println("拦截操作执行");
              //放行前逻辑
              System.out.println("放行前逻辑");
              // 放行 到达下一个filter(如果有)或者执行资源方法
              filterChain.doFilter(servletRequest,servletResponse);
              //获取资源后返回
              System.out.println("获取资源后返回");
          }
          @Override
          public void destroy() {//销毁只执行一次
              Filter.super.destroy();
          }
      }

      Filter类上加@WebFilter注解,配置拦截资源的路径。

      启动类上加@ServletComponentScan开启Servlet组件支持。

      Filter可以根据需求,配置不同的拦截资源路径:

      过滤器链

      • 介绍:一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链

        优先级是按照过滤器名字首字母顺序

        2.JWT和过滤器Filter实现登录校验

        1. 获取请求url
        2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行
        3. 获取请求头中的令牌(token)
        4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)
        5. 解析token,如果解析失败,返回错误结果(未登录)
        6. 放行
        package it.com.springbootmybatisprimary.filter;
        import com.alibaba.fastjson.JSONObject;
        import com.github.pagehelper.util.StringUtil;
        import it.com.springbootmybatisprimary.pojo.Result;
        import it.com.springbootmybatisprimary.utils.AliOSSUtils;
        import it.com.springbootmybatisprimary.utils.JwtUtils;
        import lombok.extern.slf4j.Slf4j;
        import netscape.javascript.JSObject;
        import org.springframework.util.StringUtils;
        import javax.servlet.*;
        import javax.servlet.annotation.WebFilter;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.IOException;
        @Slf4j
        @WebFilter("/*")
        public class LoginFilter implements Filter {
            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                System.out.println("拦截到请求");
                
                HttpServletRequest request = (HttpServletRequest) servletRequest;
                HttpServletResponse response = (HttpServletResponse) servletResponse;
                String url=request.getRequestURI().toString();//获取请求url
                log.info("url {}",url);
                if(url.contains("login")){//1.url包含login的话放行
                    //包含login执行放行操作并return
                    log.info("放行");
                    filterChain.doFilter(servletRequest,servletResponse);
                    return;//获取web资源后直接返回
                }
                //2.获取jwt
                String jwt = request.getHeader("token");
                //3.检查jst令牌不为空
                if(!StringUtils.hasLength(jwt)){//返回错误信息
                    Result error = Result.error("NO_LOGIN");
                    log.info("jwt令牌不存在");
                    //转化为json格式数据 利用fastjson
                   String s= JSONObject.toJSONString(error);
                     response.getWriter().write(s);
                     return;
                }
                //4.检查jwt令牌合法
                try {
                    JwtUtils.parseJWT(jwt);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.info("解析失败 返回报错");
                    Result error = Result.error("NO_LOGIN");
                    //转化为json格式数据
                    String s= JSONObject.toJSONString(error);
                    response.getWriter().write(s);
                    return;
                }
                //5.放行
                log.info("合法 放行");
                filterChain.doFilter(request,response);
            }
        }

        Postman测试

        1.含有login请求

        2.不含login请求

        3.请求头包含jwt测试

        首先获取JWT令牌

        然后emps请求携带JWT令牌测试

        控制台

        输入错误JWT 校验失败返回报错

        二.拦截器

        什么是拦截器?

        是一种动态拦截方法调用的机制,类似于过滤器。

        拦截器的作用:

        拦截请求,在指定方法调用前后,根据业务需要执行预先设定的代码。

        1.拦截器Interceptor入门

        1.定义类实现HandleInterceptor接口

        2.定义配置类实现WebMvcConfigurer

        3.postman测试

        1.放行的情况

        prehandle返回true 表示放行,执行资源方法完毕后,执行posthandle和aftercompletion

        2.不放行的情况

        prehandle返回false表示不放行一直被拦截

        2.拦截路径

        在拦截器中除了可以设置/**拦截所有资源外,还有一些常见拦截路径设置:

        拦截路径

        含义

        举例

        /*

        一级路径

        能匹配/depts,/emps,/login,不能匹配 /depts/1

        /**

        任意级路径

        能匹配/depts,/depts/1,/depts/1/2

        /depts/*

        /depts下的一级路径

        能匹配/depts/1,不能匹配/depts/1/2,/depts

        /depts/**

        /depts下的任意级路径

        能匹配/depts,/depts/1,/depts/1/2,不能匹配/emps/1

         

        • 在controller当中的方法执行完毕之后,再回过来执行

          postHandle()这个方法以及afterCompletion() 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。

          3.拦截器与过滤器执行时机

          • 当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。
          • Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。
          • 当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行

            拦截器与过滤器的区别:

            • 接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。
            • 拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。

              postman测试控制台输出日志

              2.拦截器InterCeptor实现登录校验功能

              在放行前进行登录校验所以在prehandle函数进行

              与过滤器实现登录校验逻辑一致,直接复制修改一下

              放行操作改为return true 不放行操作改为return false

              类型就是Http类型不用强转

              @Slf4j
              @Component
              public class LoginCheckInterceptor implements HandlerInterceptor {
                  @Override
                  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                      System.out.println("执行preHandle");//访问资源前执行 return true表示放行 false表示拦截
                    /*  System.out.println("filter拦截到请求");*/
                      //强转 能够调HttpServletRequest和HttpServletResponse接口中特有的方法和属性,这些方法和属性在更通用的
                      //ServletRequest和ServletResponse接口中并不存在。例如要获取请求的URL/getRequestURI())、查询参数(
                      //getParameter())、请求头(getHeader())等
                      String url = request.getRequestURI().toString();//获取请求url
                      log.info("url {}", url);
                      if (url.contains("login")) {//1.url包含login的话放行
                          //包含login执行放行操作并return
                       /*   log.info("filter放行");*/
                         return true;
                         /* System.out.println("filter放行后");*/
                      }
                      //2.获取请求jwt
                      String jwt = request.getHeader("token");//获取token携带的jwt
                      //3.检查jst令牌不为空
                      if (!StringUtils.hasLength(jwt)) {//返回错误信息
                          Result error = Result.error("NO_LOGIN");
                          log.info("jwt令牌不存在");
                          //转化为json格式数据 利用fastjson
                          String s = JSONObject.toJSONString(error);
                          response.getWriter().write(s);
                          return true;
                      }
                      //4.检查jwt令牌合法
                      try {
                          JwtUtils.parseJWT(jwt);
                      } catch (Exception e) {
                          e.printStackTrace();
                          log.info("解析失败 返回报错");
                          Result error = Result.error("NO_LOGIN");
                          //转化为json格式数据
                          String s = JSONObject.toJSONString(error);
                          response.getWriter().write(s);//写入响应体(getWriter().write())
                          return false;
                      }
                      //5.放行
                      log.info("合法 放行");
                      /*filterChain.doFilter(request, response);//继续过滤器链*/
                      return true;
                  }
                  @Override
                  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                      System.out.println("执行postHandle");//资源方法执行后执行
                  }
                  @Override
                  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
                      System.out.println("执行afterCompletion");//视图渲染后执行
                  }
              }

              postman测试

               

转载请注明来自码农世界,本文标题:《过滤器Filter和拦截器Interceptor实现登录校验》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,62人围观)参与讨论

还没有评论,来说两句吧...

Top