登录认证功能的统一拦截技术(拦截器)

2023-10-26

目录

1.说明

2.使用方法

(1) 定义拦截器

(2)注册配置拦截器

(3)示例:

3.interceptor详细说明

(1)拦截路径

(2)执行流程

(3)过滤器和拦截器的区别

4.登录校验的拦截器实现

5.全局异常处理(补充说明)


1.说明

拦截器是一种动态拦截方法调用的机制,类似于过滤器。
拦截器是Spring框架中提供的,用来动态拦截控制器方法的执行。

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

在拦截器当中,我们通常也是做一些通用性的操作,比如:我们可以通过拦截器来拦截前端发起的请求,将登录校验的逻辑全部编写在拦截器当中。在校验的过程当中,如发现用户登录了(携带JWT令牌且是合法令牌),就可以直接放行,去访问spring当中的资源。如果校验时发现并没有登录或是非法令牌,就可以直接给前端响应未登录的错误信息。

2.使用方法

(1) 定义拦截器

实现HandlerInterceptor接口,并重写其所有方法

//自定义拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
    //目标资源方法执行前执行。 返回true:放行    返回false:不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle .... ");

        return true; //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 .... ");
    }
}

注意:
preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行。
postHandle方法:目标资源方法执行后执行。
afterCompletion方法:视图渲染完毕后执行,最后执行。

(2)注册配置拦截器

实现WebMvcConfigurer接口,并重写addInterceptors方法。

@Configuration  
public class WebConfig implements WebMvcConfigurer {

    //自定义的拦截器对象
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //注册自定义拦截器对象
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
    }
}

(3)示例:

package com.example.demo.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author linaibo
 * @Date 2023/4/9 15:29
 * @PackageName:com.example.demo.interceptor
 * @ClassName: DemoInterceptor
 * @Version 1.0
 */
@Component
public class DemoInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("方法执行前");
        // 返回true,代表放行。返回false,代表不放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法执行后");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("视图渲染完毕后执行");
    }
}
package com.example.demo.config;

import com.example.demo.interceptor.DemoInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author linaibo
 * @Date 2023/4/9 15:33
 * @PackageName:com.example.demo.config
 * @ClassName: WebConfig
 * @Version 1.0
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private DemoInterceptor demoInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(demoInterceptor).addPathPatterns("/**");
    }
}

3.interceptor详细说明

(1)拦截路径

首先我们先来看拦截器的拦截路径的配置,在注册配置拦截器的时候,我们要指定拦截器的拦截路径,通过addPathPatterns("要拦截路径")方法,就可以指定要拦截哪些资源。

在入门程序中我们配置的是`/**`,表示拦截所有资源,而在配置拦截器时,不仅可以指定要拦截哪些资源,还可以指定不拦截哪些资源,只需要调用`excludePathPatterns("不拦截路径")`方法,指定哪些资源不需要拦截。

例:

@Configuration  
public class WebConfig implements WebMvcConfigurer {

    //拦截器对象
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自定义拦截器对象
        registry.addInterceptor(loginCheckInterceptor)
                .addPathPatterns("/**")//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
                .excludePathPatterns("/login");//设置不拦截的请求路径
    }
}

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

(2)执行流程

当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。
Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。
当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行`preHandle()`方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。
在controller当中的方法执行完毕之后,再回过来执行`postHandle()`这个方法以及`afterCompletion()` 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。 

(3)过滤器和拦截器的区别

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

4.登录校验的拦截器实现

登录校验拦截器

//自定义拦截器
@Component //当前拦截器对象由Spring创建和管理
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    //前置方式
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle .... ");
        //1.获取请求url
        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行

        //3.获取请求头中的令牌(token)
        String token = request.getHeader("token");
        log.info("从请求头中获取的令牌:{}",token);

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(token)){
            log.info("Token不存在");

            //创建响应结果对象
            Result responseResult = Result.error("NOT_LOGIN");
            //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            //设置响应头(告知浏览器:响应的数据类型为json、响应的数据编码表为utf-8)
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);

            return false;//不放行
        }

        //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(token);
        }catch (Exception e){
            log.info("令牌解析失败!");

            //创建响应结果对象
            Result responseResult = Result.error("NOT_LOGIN");
            //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            //设置响应头
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);

            return false;
        }

        //6.放行
        return true;
    }

注册配置拦截器

@Configuration  
public class WebConfig implements WebMvcConfigurer {
    //拦截器对象
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //注册自定义拦截器对象
        registry.addInterceptor(loginCheckInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

5.全局异常处理(补充说明)

* 定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器。
* 在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。

示例:

@RestControllerAdvice
public class GlobalExceptionHandler {

    //处理异常
    @ExceptionHandler(Exception.class) //指定能够处理的异常类型
    public Result ex(Exception e){
        e.printStackTrace();//打印堆栈中的异常信息

        //捕获到异常之后,响应一个标准的Result
        return Result.error("对不起,操作失败,请联系管理员");
    }
}

@RestControllerAdvice = @ControllerAdvice + @ResponseBody
处理异常的方法返回值会转换为json后再响应给前端

全局异常处理器的使用,主要涉及到两个注解:

@RestControllerAdvice //表示当前类为全局异常处理器
@ExceptionHandler //指定可以捕获哪种类型的异常进行处理

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

登录认证功能的统一拦截技术(拦截器) 的相关文章

  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • .properties 中的通配符

    是否存在任何方法 我可以将通配符添加到属性文件中 并且具有所有含义 例如a b c d lalalala 或为所有以结尾的内容设置一个正则表达式a b c anything 普通的 Java 属性文件无法处理这个问题 不 请记住 它实际上是
  • 如何更改javaFX中按钮的图像?

    我正在使用javaFX 我制作了一个按钮并为此设置了图像 代码是 Image playI new Image file c Users Farhad Desktop icons play2 jpg ImageView iv1 new Ima
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 在接口中使用默认方法是否违反接口隔离原则?

    我正在学习 SOLID 原则 ISP 指出 客户端不应被迫依赖于他们所使用的接口 不使用 在接口中使用默认方法是否违反了这个原则 我见过类似的问题 但我在这里发布了一个示例 以便更清楚地了解我的示例是否违反了 ISP 假设我有这个例子 pu
  • 来自 dll 的 Java 调用函数

    我有这个 python 脚本导入zkemkeeperdll 并连接到考勤设备 ZKTeco 这是我正在使用的脚本 from win32com client import Dispatch zk Dispatch zkemkeeper ZKE
  • 没有 Spring 的自定义 Prometheus 指标

    我需要为 Web 应用程序提供自定义指标 问题是我不能使用 Spring 但我必须使用 jax rs 端点 要求非常简单 想象一下 您有一个包含键值对的映射 其中键是指标名称 值是一个简单的整数 它是一个计数器 代码会是这样的 public
  • 在 junit 测试中获取 javax.lang.model.element.Element 类

    我想测试我的实用程序类 ElementUtils 但我不知道如何将类作为元素获取 在 AnnotationProcessors 中 我使用以下代码获取元素 Set
  • 帮助将图像从 Servlet 获取到 JSP 页面 [重复]

    这个问题在这里已经有答案了 我目前必须生成一个显示字符串文本的图像 我需要在 Servlet 上制作此图像 然后以某种方式将图像传递到 JSP 页面 以便它可以显示它 我试图避免保存图像 而是以某种方式将图像流式传输到 JSP 自从我开始寻
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 长轮询会冻结浏览器并阻止其他 ajax 请求

    我正在尝试在我的中实现长轮询Spring MVC Web 应用程序 http static springsource org spring docs 2 0 x reference mvc html但在 4 5 个连续 AJAX 请求后它会

随机推荐

  • flutter毛玻璃效果

    ClipRect child BackdropFilter filter ImageFilter blur sigmaX 3 0 sigmaY 3 0 child Opacity opacity 0 3 child Container de
  • 2.2算法描述及设计原则

    一 算法的常见描述方法 可以用多种形式 选择其一即可 具体 计算机程序设计语言 自然语言 PDL语言 也称伪程序设计语言 或伪码语言 可运行于 抽象计算机 虚拟机 流程图 框图 或N S图 二 算法设计须遵循的一般准则 一般来说有下面四个目
  • 算法与数据结构基础<四>----动态数据结构基础:链表

    接着上一次算法与数据结构基础 lt 三 gt 数据结构基础之栈和队列加强之用栈实现队列 cexo 博客园的数据结构继续往下学习 这次会进入一个非常重要的数据结构的学习 链表 这个是未来学习复杂算法的一个基础 大量会被用到 所以 先夯实好基础
  • 在react 中使用 Swiper@6.8.4 -(解决initialSlide初始化设置无效问题)

    下载Swiper yarn add swiper 6 8 4 基础使用 引入模块 import Swiper SwiperSlide from swiper react import swiper swiper bundle css 基础使
  • 一个项目学会tensorflow2.0

    优化 1 使用数据增强技术 2 使用数据生成器提高训练速度 3 调节超参数 提高模型精度 4 使用VGG技术迁移学习 提高训练速度 目标 算法应用 熟练掌握TensorFlow框架使用 掌握神经网络图像相关案例 1 训练的时候读取本地图片以
  • Failed to fetch https://mirrors.tuna.tsinghua.edu.cn/ubuntu//dists/bionic/main/binary-arm64/Packages

    转载自 Failed to fetch https mirrors tuna tsinghua edu cn ubuntu dists bionic main binary arm64 Packages anthony 36的博客 CSDN
  • echarts图表的x轴和y轴的配置

    xAxis与yAxis中有很多配置项 下面我以xAxis进行详解 yAxis参考xAxis即可 nameTextStyle 坐标轴名称的文字样式 axisLine 坐标轴轴线相关设置 axisTick 坐标轴刻度相关设置 axisLabel
  • bean的一生----Spring容器启动

    1 我这里通过AnnotationConfigApplicationContext来new一个容器对象 可以看到构造方法实现了三个方法 this this register componentClasses this refresh 第一个
  • 硬件基础 - 51单片机IO口

    分析电路定律 1 回路与阻抗 2 电路设计就是波形整形过程 3 继电器 电磁 机械 开关 光耦电子 隔离开关 电气隔离 开关速度慢 三极管 电子开关 开关信号 小功率 高速 MOS 电子开关 大功率 裂变开关 晶闸管 电子开关 IGBT 电
  • 龙族幻想微信一区哪个服务器人多,龙族幻想微信一区-命运之刃开服时间表_龙族幻想新区开服预告_第一手游网手游开服表...

    2019 09 02 10 00 手Q二十四区 王者之争 已经开服 10 00 微信十一区 自由之日 已经开服 2019 08 29 10 00 手Q二十四区 逆卷刃流 已经开服 2019 08 28 10 00 微信十一区 风暴裂隙 已经
  • vivado路径最大时钟约束_【vivado约束学习二】 IO延时约束

    vivado约束学习二 IO延时约束 1 I O延迟约束介绍 要在设计中精确建模外部时序 必须为输入和输出端口提供时序信息 Xilinx Vivado集成设计环境 IDE 仅在FPGA边界内识别时序 因此必须使用以下命令指定超出这些边界的延
  • 全球及中国芯片产业研发方向与投资规模预测报告2022版

    全球及中国芯片产业研发方向与投资规模预测报告2022版 HS HS HS HS HS HS HS HS HS HS HS HS 修订日期 2021年11月 搜索鸿晟信合研究院查看官网更多内容 第一章 芯片相关概念介绍 1 1 芯片的概念 1
  • QML实现Label的文字选择与右键各操作

    在QML中 原生的Label是不能够进行鼠标的选中 复制 全选等操作的 仅仅只能用于简单的展示文字 但是在实际开发中 往往我们需要给用户展示一些信息 而且要支持可以用鼠标进行选择文字 并进行复制操作 所以 用QML中的Label控件显然是不
  • 信息安全意识主题分享-数据安全

    微盟删库 事件沸沸扬扬 这次重大的数据违规行为 导致微盟的股市市值暴跌12亿港币 影响巨大 本文主要为大家介绍针对数据安全的威胁和风险 有哪些安全防护措施 一 数据简介 1 数据的形态 数据主要可以分为两种形态 也就是平时常见的数据的表现方
  • coco游戏android.mk

    LOCAL PATH call my dir include CLEAR VARS LOCAL MODULE game shared LOCAL MODULE FILENAME libgame LOCAL CPP EXTENSION cc
  • 4G版本云音响设置教程阿里云平台版本

    4G版本云音响设置教程介绍 第一章 介绍了在阿里云物联网平台生一个设备使用的三元素 第二章 转换阿里云三元素 为MQTT参数 并下载到设备中 第三章 阿里云物联网套件协议使用说明 如何发送数据至设备并播放 本文目录引导 目录 4G版本云音响
  • egg-jwt的使用

    安装 npm install egg jwt save 配置 config config default js config jwt secret zidingyi 自定义 token 的加密条件字符串 config plugin js j
  • RPC答疑篇

    声明 本篇文章及代码仅供学习交流 严禁用于商业用途 否则由此产生的一切后果均与作者无关 上一篇的rpc发出来后 虽然我觉得我已经写得很细致了 但还是收到了很多私信说是跑不成功 所以再发 水 一篇 关于如何操作的文章 鉴于很多人没有某店的账号
  • Spring-Cloud-Alibaba之Dubbo

    在微服务构架中 不可避免的要遇到服务间的调用 目前的方式是通过RPC或者是rest的http接口调用 spring cloud中很多都使用的feign来做服务调用 在spring cloud alibaba的套装中我们使用dubbo来替换掉
  • 登录认证功能的统一拦截技术(拦截器)

    目录 1 说明 2 使用方法 1 定义拦截器 2 注册配置拦截器 3 示例 3 interceptor详细说明 1 拦截路径 2 执行流程 3 过滤器和拦截器的区别 4 登录校验的拦截器实现 5 全局异常处理 补充说明 1 说明 拦截器是一