做视频网站/百度推广怎么做最好
统一拦截
上文我们提到(登录认证(4):令牌技术),现在大部分项目都使用JWT令牌
来进行会话跟踪,来完成登录功能。有了JWT令牌
可以标识用户的登录状态,但是完整的登录逻辑如图所示:
我们还需要一个统一拦截器
,用于拦截用户的请求,在拦截器中,我们需要验证用户的JWT令牌
,来判断用户是否登录,从而进行放行或拦截。统一拦截一般有两种解决方案:Filter过滤器和Interceptor拦截器,本文先讲解Filter过滤器。
Filter过滤器
工作原理
Filter
的本意就是过滤器,在JavaWeb
中是用于过滤请求的,是JavaWeb的三大核心组件之一 (Servlet
、Filter
、Listener
)。Filter过滤器
的工作原理就是将客户端发起的对服务端资源的请求拦截下来,进行处理,从而实现一些特殊功能。
当程序使用了Filter过滤器
之后,请求想要访问服务端的资源,就必须先经过过滤器
,待过滤器处理完毕放行之后,才可以访问对应的资源。Filter过滤器
一般用于完成一些通用的操作,比如:登录校验、敏感字符处理等。
快速入门
Filter过滤器
的快速入门十分简单,主要步骤分为两步:首先需要定义过滤器,定义一个类,实现Filter接口
,并重写其中所有方法;然后需要配置过滤器,在Filter类
上添加@WebFilter注解
,配置拦截资源的路径(只有请求对应的资源才会被过滤器拦截)。假如使用SpringBoot
构建项目,还需要在引导类
上添加@ServletComponentScan注解
开启Servlet组件支持。
定义过滤器
定义Filter过滤器
的代码:
public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("Init Filter");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {log.info("Filter 成功拦截请求");}@Overridepublic void destroy() {log.info("Destroy Filter");}
}
定义Filter过滤器
的代码很简单,首先需要定义一个类实现Filter接口,然后重写Filter接口
中的三个方法。
init方法
顾名思义,init方法
是Filter过滤器
的初始化方法,在服务器启动时,会自动创建Filter过滤器
对象,在创建过滤器对象的时候,就会自动调用init初始化方法初始化过滤器,并且这个方法只会被调用一次。
doFilter方法
doFilter方法
是过滤器的核心部分,该方法在过滤器每一次拦截到了请求之后都会被调用,一般而言,这个方法会被调用多次,每一次拦截到请求,都会调用一次doFilter方法
,而我们就可以在doFilter方法
中实现一些功能,比如说对这次请求的JWT令牌
进行解析,以此判断用户的登录状态。
destroy方法
destroy方法
是销毁过滤器的方法,当服务器关闭时,会自动调用destroy方法销毁过滤器,destroy方法也只会被调用一次。
配置过滤器
在定义Filter过滤器
之后,过滤器并不会生效,此时还需要完成Filter
过滤器的配置,过滤器的配置相对简单,只需要在Filter类
上添加@WebFilter
注解,并在其urlPatterns属性
中指定需要拦截的请求路径。
@Slf4j
@WebFilter(urlPatterns = "/*") // 配置Filter过滤器的拦截请求路径,/*表示拦截所有
public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("Init Filter");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {log.info("Filter 成功拦截请求");}@Overridepublic void destroy() {log.info("Destroy Filter");}
}
通过/*
通配符表示拦截所有请求(所有请求都会被过滤器所拦截,可以根据不同的需求更改路径),这样就完成了Filter过滤器
的配置,当定义和配置都完成之后,Filter过滤器
就可以真正开始工作了,此时启动服务器进行测试:
如图所示,在服务器启动的时候,自动创建Filter过滤器
,并调用了其init方法
,初始化过滤器。此时向服务端发起请求:
如图所示,发起的请求成功被Filter过滤器
拦截,但是客户端并没有得到服务器响应的数据
这是因为在Filter过滤器
中,必须要执行放行操作,才可以访问到服务器中的资源,可以通过FilterChain实体类
中的doFilter
方法放行:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {log.info("Filter 成功拦截请求");filterChain.doFilter(servletRequest, servletResponse);
}
放行之后再发起请求,就可以成功访问到服务器中的资源了:
关闭服务器,发现Filter过滤器
自动调用destroy方法销毁:
登录校验过滤器
通过上文的快速入门,我们已经了解了如何创建并配置一个Filter过滤器
,那么回归到主线,使用Filter过滤器
完成登录校验功能。
实现逻辑
让我们回顾一下登录校验的实现逻辑:用户登录时需要访问登录接口login
,当用户输入的用户名和密码验证成功之后,会生成一个JWT令牌
,并且将JWT令牌
返回给客户端,客户端
会将JWT
存储起来,然后在后续的每一次请求中,都携带这个JWT令牌
到服务端,这个时候,就需要Filter过滤器
进行工作了:在登录校验中,Filter过滤器必须要验证JWT令牌
的有效性,如果令牌能够成功解析,则证明为有效令牌;反之则为无效令牌。若令牌有效,Filter过滤器
则放行请求,让它访问服务端对应的资源;如果为无效令牌,则进行拦截
,并给客户端响应一个错误的信息(401)。其流程如图所示:
这样,登录校验的实现逻辑已经比较清晰了,但需要注意一点:对于登录(login)请求,过滤器是不需要进行拦截的,因为用户发起登录请求,就是为了获得JWT令牌
,其本身是没有JWT令牌
的,如果进行拦截,那么永远都只会得到请求失败的结果。
我们上述逻辑编写登录校验过滤器
代码:
/*** 令牌校验过滤器(登录过滤器)*/
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("Init Filter");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;// 获取该请求的URLString url = httpServletRequest.getRequestURL().toString();// 判断该请求是否包含login,如果包含,说明该请求是登录,则放行if (url.contains("/login")) {log.info("login");filterChain.doFilter(httpServletRequest, httpServletResponse);return;}// 获取请求头中的token(JWT令牌)String jwt = httpServletRequest.getHeader("token");// 判断令牌是否存在,若不存在,则返回错误结果(未登录)if (jwt == null || jwt.isEmpty()) {log.info("JWT令牌为空,登录失败");httpServletResponse.setStatus(401);return;}// 解析JWT令牌,如果解析失败,则返回错误结果(未登录)try {JWTUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();log.info("JWT解析失败,登录失败");httpServletResponse.setStatus(401);return;}// 令牌解析成功,放行log.info("令牌解析成功,放行");filterChain.doFilter(httpServletRequest, httpServletResponse);}@Overridepublic void destroy() {log.info("Destroy Filter");}
}
我们配置的过滤器是会拦截所有的请求,但是这和我们分析的逻辑不一样,我们需要直接放行登录请求,所以说需要进行判断该请求是否是登录,可以根据请求路径进行判断。然后需要获取到这次请求的token
,如果请求没有一个请求头
叫token
,那么可以判断该请求没有携带JWT令牌
,表示该用户没有登录,所以说直接响应错误结果,无需进行判断,最后才是解析token,假如在解析过程中报错,那么肯定意味着JWT令牌
解析错误,意味着用户可能伪造或更改了令牌,也表示用户未登录,所以说不能放行,需要返回错误代码。如果成功解析JWT令牌
,那么就可以调用FilterChain
中的doFilter
方法,放行该请求,让它访问服务端对应的资源。这就是 登录校验
的整个流程。此时让我们发起请求进行测试:
如图所示,发起了一个非登录的请求,由于此时还没有登录,所以说没有JWT令牌
,所以说自然被Filter过滤器
所拦截,请求失败。
此时发起登录请求,由于我们的逻辑是登录请求直接放行,所以说这次请求就被Filter过滤器
放行了,成功获得了JWT令牌
。
当我们登录后获得了
JWT令牌
,之后的请求就可以在请求头
中携带JWT令牌
发起请求,这样当我们的JWT令牌
是正确的,被成功解析之后Filter过滤器
就会放行,就可以访问到对应的资源了。
Filter过滤器使用细节
Filter过滤器执行流程
Filter过滤器
执行流程如图所示:
当过滤器拦截到了请求之后,如果希望该请求访问到服务端资源,那么就需要执行doFilter
方法进行放行,在doFilter方法所编写的代码就是放行前逻辑。但是值得注意的是——请求访问完资源之后,还会回到过滤器当中,如果有需求,回到过滤器之后还可以执行放行后逻辑,放行后逻辑就是doFilter方法
之后的代码。
Filter过滤器拦截路径
可以根据不同的需求,配置不同的拦截路径,下面介绍几种常见的拦截路径:像/login这样的拦截路径属于具体拦截
路径,只有请求路径为/login
时,拦截器才会拦截;像/emps/*这样的拦截路径属于目录拦截
,访问/emps下的所有资源的请求,都会被拦截;像/*这样的拦截路径十分简单粗暴,会拦截所有请求
。可以根据不同的需求,灵活的配置拦截路径。
过滤器链
在一个web应用程序
中,可以根据需求,配置多个拦截器,这样的多个拦截器就形成了一个过滤器链:
如图所示,在web服务端
中,定义了两个Filter过滤器
,这两个过滤器就形成了一个过滤器链,过滤器链上的过滤器会一个一个的执行,先执行第一个;再执行第二个,必须要过滤器链上的最后一个过滤器放行后(也代表着所有过滤器都必须放行),请求才能访问到对应的资源。但是当请求返回时,会根据相反的顺序,通过过滤器链,先执行过滤器2;再执行过滤器1,最后给客户端响应数据。
并且,过滤器链的执行顺序,是根据过滤器名(字符串)的自然排序的,比如AbcFilter
会先于DemoFilter
执行。
总结
Filter过滤器
是Servlet
中的技术,是用于统一拦截的
,想要在web程序
中使用过滤器,就需要定义一个过滤器,并且配置过滤器,定义其拦截路径,我们可以在Filter过滤器
的doFilter
方法中编写一些逻辑决定该过滤器的放行逻辑,从而实现登录校验功能。Spring框架
中也提供了一个类似过滤器的Interceptor拦截器
,且听下回分解。
相关文章:

登录认证(5):过滤器:Filter
统一拦截 上文我们提到(登录认证(4):令牌技术),现在大部分项目都使用JWT令牌来进行会话跟踪,来完成登录功能。有了JWT令牌可以标识用户的登录状态,但是完整的登录逻辑如图所示&…...

pytorch实现门控循环单元 (GRU)
人工智能例子汇总:AI常见的算法和例子-CSDN博客 特性GRULSTM计算效率更快,参数更少相对较慢,参数更多结构复杂度只有两个门(更新门和重置门)三个门(输入门、遗忘门、输出门)处理长时依赖一般适…...

Word List 2
词汇颜色标识解释 词汇表中的生词 词汇表中的词组成的搭配、派生词 例句中的生词 我自己写的生词(用于区分易混淆的词,无颜色标识) 不认识的单词或句式 单词的主要汉语意思 不太理解的句子语法和结构 Word List 2 英文音标中文regi…...

机器学习常用包numpy篇(四)函数运算
目录 前言 一、三角函数 二、双曲函数 三、数值修约 四、 求和、求积与差分 五、 指数与对数 六、算术运算 七、 矩阵与向量运算 八、代数运算 九、 其他数学工具 总结 前言 Python 的原生运算符可实现基础数学运算(加减乘除、取余、取整、幂运算&#…...

CSS in JS
css in js css in js 的核心思想是:用一个 JS 对象来描述样式,而不是 css 样式表。 例如下面的对象就是一个用于描述样式的对象: const styles {backgroundColor: "#f40",color: "#fff",width: "400px",he…...

TCP 丢包恢复策略:代价权衡与优化迷局
网络物理层丢包是一种需要偿还的债务,可以容忍低劣的传输质量,这为 UDP 类服务提供了空间,而对于 TCP 类服务,可以用另外两类代价来支付: 主机端采用轻率的 GBN 策略恢复丢包,节省 CPU 资源,但…...

面经--C语言——内存泄漏、malloc和new的区别 .c文件怎么转换为可执行程序 uart和usart的区别 继承的访问权限总结
文章目录 内存泄漏预防内存泄漏的方法: malloc和new的区别.c文件怎么转换为可执行程序uart和usart的区别继承的访问权限总结访问控制符总结1. **public**:2. **protected**:3. **private**:继承类型: 内存泄漏 内存泄漏是指程序在运行时动态分配内存后&…...

Denavit-Hartenberg DH MDH坐标系
Denavit-Hartenberg坐标系及其规则详解 6轴协作机器人的MDH模型详细图_6轴mdh-CSDN博客 N轴机械臂的MDH正向建模,及python算法_mdh建模-CSDN博客 运动学3-----正向运动学 | 鱼香ROS 机器人学:MDH建模 - 哆啦美 - 博客园 机械臂学习——标准DH法和改进MDH…...

力扣动态规划-20【算法学习day.114】
前言 ###我做这类文章一个重要的目的还是记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴!!! 习题 1.网格中的最小路径代价 题目链接…...

计算机视觉-边缘检测
一、边缘 1.1 边缘的类型 ①实体上的边缘 ②深度上的边缘 ③符号的边缘 ④阴影产生的边缘 不同任务关注的边缘不一样 1.2 提取边缘 突变-求导(求导也是一种卷积) 近似,1(右边的一个值-自己可以用卷积做) 该点f(x,y)…...

文字加持:让 OpenCV 轻松在图像中插上文字
前言 在很多图像处理任务中,我们不仅需要提取图像信息,还希望在图像上加上一些文字,或是标注,或是动态展示。正如在一幅画上添加一个标语,或者在一个视频上加上动态字幕,cv2.putText 就是这个“文字魔术师”,它能让我们的图像从“沉默寡言”变得生动有趣。 今天,我们…...

掌握 HTML5 多媒体标签:如何在所有浏览器中顺利嵌入视频与音频
系列文章目录 01-从零开始学 HTML:构建网页的基本框架与技巧 02-HTML常见文本标签解析:从基础到进阶的全面指南 03-HTML从入门到精通:链接与图像标签全解析 04-HTML 列表标签全解析:无序与有序列表的深度应用 05-HTML表格标签全面…...

在Mac mini M4上部署DeepSeek R1本地大模型
在Mac mini M4上部署DeepSeek R1本地大模型 安装ollama 本地部署,我们可以通过Ollama来进行安装 Ollama 官方版:【点击前往】 Web UI 控制端【点击安装】 如何在MacOS上更换Ollama的模型位置 默认安装时,OLLAMA_MODELS 位置在"~/.o…...

【电脑系统】电脑突然(蓝屏)卡死发出刺耳声音
文章目录 前言问题描述软件解决方案尝试硬件解决方案尝试参考文献 前言 在 更换硬盘 时遇到的问题,有时候只有卡死没有蓝屏 问题描述 更换硬盘后,电脑用一会就卡死,蓝屏,显示蓝屏代码 UNEXPECTED_STORE_EXCEPTION 软件解决方案…...

Docker使用指南(二)——容器相关操作详解(实战案例教学,创建/使用/停止/删除)
目录 1.容器操作相关命令编辑 案例一: 案例二: 容器常用命令总结: 1.查看容器状态: 2.删除容器: 3.进入容器: 二、Docker基本操作——容器篇 1.容器操作相关命令 下面我们用两个案例来具体实操一…...

Java中的常见对象类型解析
在Java开发中,数据的组织和传递是一个重要的概念。为了确保代码的清晰性、可维护性和可扩展性,我们通常会根据不同的用途,设计和使用不同类型的对象。这些对象的作用各不相同,但它们共同为构建高效、模块化的软件架构提供支持。 …...

Dijkstra算法解析
Dijkstra算法,用于求解图中从一个起点到其他所有节点的最短路径。解决单源最短路径问题的有效方法。 条件 有向 带权路径 时间复杂度 O(n平方) 方法步骤 1 把图上的点分为两个集合 要求的起点 和除了起点之外的点 。能直达的写上权值 不…...

C++ Primer 多维数组
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...

maven mysql jdk nvm node npm 环境安装
安装JDK 1.8 11 环境 maven环境安装 打开网站 下载 下载zip格式 解压 自己创建一个maven库 以后在idea 使用maven时候重新设置一下 这三个地方分别设置 这时候maven才算设置好 nvm 管理 npm nodejs nvm下载 安装 Releases coreybutler/nvm-windows GitHub 一键安装且若有…...

SQL Server中RANK()函数:处理并列排名与自然跳号
RANK()是SQL Server的窗口函数,为结果集中的行生成排名。当出现相同值时,后续排名会跳过被占用的名次,形成自然间隔。与DENSE_RANK()的关键区别在于是否允许排名值连续。 语法: RANK() OVER ([PARTITION BY 分组列]ORDER BY 排序…...

如何运行Composer安装PHP包 安装JWT库
1. 使用Composer Composer是PHP的依赖管理工具,它允许你轻松地安装和管理PHP包。对于JWT,你可以使用firebase/php-jwt这个库,这是由Firebase提供的官方库。 安装Composer(如果你还没有安装的话): 访问Co…...

最新功能发布!AllData数据中台核心菜单汇总
🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨奥零数据科技官网:http://www.aolingdata.com ✨AllData开源项目:https://github.com/alldatacenter/…...

【OS】AUTOSAR架构下的Interrupt详解(上篇)
目录 前言 正文 1.中断概念分析 1.1 中断处理API 1.2 中断级别 1.3 中断向量表 1.4 二类中断的嵌套 1.4.1概述 1.4.2激活 1.5一类中断 1.5.1一类中断的实现 1.5.2一类中断的嵌套 1.5.3在StartOS之前的1类ISR 1.5.4使用1类中断时的注意事项 1.6中断源的初始化 1.…...

大数据挖掘--两个角度理解相似度计算理论
文章目录 0 相似度计算可以转换成什么问题1 集合相似度的应用1.1 集合相似度1.1文档相似度1.2 协同过滤用户-用户协同过滤物品-物品协同过滤 1.2 文档的shingling--将文档表示成集合1.2.1 k-shingling1.2.2 基于停用词的 shingling 1.3 最小哈希签名1.4 局部敏感哈希算法&#…...

Win10微软商店重新安装指南
Win10微软商店重新安装指南 在使用Windows 10操作系统的过程中,微软商店(Microsoft Store)作为官方提供的应用下载平台,一直是用户获取和安装各类应用程序的重要渠道。然而,有时用户可能会遇到微软商店无法找到或误删的情况,这无疑给软件的安装和管理带来了不便。本文将…...

操作系统和中间件的信息收集
在浏览器中收集操作系统与中间件信息时,主要通过客户端JavaScript(用于操作系统/浏览器信息)和服务器端脚本(用于中间件信息)实现。以下是分步指南: 一、客户端操作系统信息收集(JavaScript&am…...

项目集成Spring Security授权部分
一、需求分析 业务背景 当前项目采用前后端分离架构,后端需要对接口访问进行严格控制,防止未授权访问。鉴于系统需要支持高并发与分布式部署,采用无状态认证方式显得尤为重要。 核心需求 无状态认证:使用 JWT 作为令牌࿰…...

5. k8s二进制集群之ETCD集群部署
下载etcd安装包创建etcd配置文件准备证书文件和etcd存储目录ETCD证书文件安装(分别对应指定节点)创建证书服务的配置文件启动etcd集群验证etcd集群状态继续上一篇文章《k8s二进制集群之ETCD集群证书生成》下面介绍一下etcd证书生成配置。 下载etcd安装包 https://github.com…...

MV结构下设置Qt表格的代理
目录 预备知识 模型 关联 刷新 示例 代理 模型 界面 结果 完整资料见: 所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客…...

二维数组 C++ 蓝桥杯
1.稀疏矩阵 #include<iostream> using namespace std;const int N 1e4 10; int a[N][N];int main() {int n, m; cin >> n >> m;for (int i 1; i < n; i) {for (int j 1; j < m; j) {cin >> a[i][j];}}for (int j m; j > 1; j--) {for (i…...