登录校验---Filter过滤器

news/2025/10/13 23:41:04/文章来源:https://www.cnblogs.com/Lantz12/p/19139672

过滤器(Filter)

  • 概念: Filter 过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
  • 过滤器一般完成一些通用的操作,比如: 登录校验、统一编码处理、敏感字符处理等。

img

代码演示

步骤

自定义Filter:继承Filter并且重写其方法(主要重写doFilter()

配置Filter:配置@WebFilter(urlPatterns = ("/*"))以及拦截路径,并且在启动类添加注解@ServletComponentScan开启Servlet组件支持

@WebFilter(urlPatterns = ("/*"))
public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("init 初始化拦截器...");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("拦截到了请求...放行前");// 放行filterChain.doFilter(servletRequest, servletResponse);System.out.println("拦截到了请求...放行后");}@Overridepublic void destroy() {System.out.println("destroy方法执行...");}
}

方法介绍

init():初始化方法,Web 服务器启动,创建Filter时调用,只调用一次

doFilter():拦截到了请求,并执行该方法,可多次调用,注意关键的实现filterChain.doFilter()以及拦截前后的逻辑实现

destroy():销毁方法,服务器关闭执行,只调用一次

拦截路径设置

拦截路径 urlPatterns值 含义
拦截具体路径 /login 只有访问 /login 路径时,才会被拦截
目录拦截 /emps/* 访问/emps下的所有资源,都会被拦截
拦截所有 /* 访问所有资源,都会被拦截

过滤器链

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

执行顺序: 注解配置的Filter,优先级是按照过滤器类名(字符串A, B, C, ....)的自然排序。

img

扩展知识点(doFilter()

通过校验请求认证头(authHeader)所携带的token去校验,我在Postman中使用的是Bearer Token身份校验,Bearer Token 在请求头中以 Bearer 关键字加上令牌本身的形式发送,格式通常为Authorization: Bearer <token>。详细可看Apifox--什么是Bearer Token

img

代码展示 --- doFilter()

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;// 设置响应头setupResponseHeaders(httpResponse);// 处理预检请求if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {httpResponse.setStatus(HttpServletResponse.SC_OK);return;}// 获取请求路径String requestPath = httpRequest.getRequestURI();String contextPath = httpRequest.getContextPath();String path = requestPath.substring(contextPath.length());// 检查是否为排除路径if (isExcludePath(path)) {chain.doFilter(request, response);return;}// 获取认证头部String authHeader = httpRequest.getHeader(AUTH_HEADER);// 检查认证头是否存在且格式正确if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) {sendUnauthorizedResponse(httpResponse, "请先登录");return;}// 提取 JWT 令牌String jwtToken = authHeader.substring(BEARER_PREFIX.length()).trim();try {// 验证 JWT 令牌if (!JwtUtils.validateToken(jwtToken)) {sendUnauthorizedResponse(httpResponse, "令牌无效或已过期");return;}// 从 JWT 中解析用户信息Long userId = JwtUtils.getUserIdFromToken(jwtToken);String userAccount = JwtUtils.getUserAccountFromToken(jwtToken);String userName = JwtUtils.getUserNameFromToken(jwtToken);// 将用户信息放入请求属性,供后续使用httpRequest.setAttribute("id", userId);httpRequest.setAttribute("userAccount", userAccount);httpRequest.setAttribute("userName", userName);System.out.println("JWT认证成功 - 用户ID: " + userId + ", 账号: " + userAccount);// 继续过滤器链chain.doFilter(request, response);} catch (Exception e) {sendUnauthorizedResponse(httpResponse, "令牌解析失败: " + e.getMessage());}
}

封装方法

在执行过滤器中,除了校验令牌,我们还要做其他的工作

1)排除不需要认证的路径

检查是否为排除路径(不需要认证的路径):比如登录、注册等等

// 排除认证的路径
private static final String[] EXCLUDE_PATHS = {"/user/login","/user/register","/doc.html","/webjars/","/swagger-resources","/v2/api-docs"
};
/*** 检查是否为排除路径(不需要认证的路径)*/
private boolean isExcludePath(String path) {
for (String excludePath : EXCLUDE_PATHS) {if (path.startsWith(excludePath)) {return true;}
}
return false;

2)设置响应头

主要处理CORS(跨域资源共享)配置和字符编码

/*** 设置响应头*/
private void setupResponseHeaders(HttpServletResponse response) {response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With");response.setHeader("Access-Control-Max-Age", "3600");response.setCharacterEncoding("UTF-8");response.setContentType("application/json;charset=UTF-8");
}

作用:

Access-Control-Allow-Origin: "*"

  • 允许所有域名访问你的 API
  • 如果是生产环境,建议改为具体域名:"http://your-frontend.com"

Access-Control-Allow-Methods: "GET, POST, PUT, DELETE, OPTIONS"

  • 允许前端使用这些 HTTP 方法

Access-Control-Allow-Headers: "Authorization, Content-Type, X-Requested-With"

  • 允许前端发送这些自定义请求头
  • 特别重要:包含了 Authorization,这样前端才能发送 JWT Token

Access-Control-Max-Age: "3600"

  • 预检请求缓存时间(1小时),减少重复的 OPTIONS 请求

什么是 OPTIONS 请求

OPTIONS 是 HTTP 方法之一,用于获取目标资源支持的通信选项。在 CORS 中,浏览器会自动发送 OPTIONS请求来检查是否允许跨域访问。

什么时候会发送 OPTIONS 请求

触发条件

跨域请求(域名、端口、协议不同)

非简单请求(满足以下任一条件):

简单请求(不会触发 OPTIONS):

GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://frontend.com

非简单请求(会触发 OPTIONS):
自定义请求头

POST /api/user HTTP/1.1
Host: localhost:8080
Origin: http://localhost:3000
Authorization: Bearer token123  # 自定义头
X-Custom-Header: value         # 自定义头

非简单 Content-Type

POST /api/user HTTP/1.1
Content-Type: application/json  # 非简单 Content-Type

非简单 HTTP 方法

PUT /api/user/1 HTTP/1.1
PATCH /api/user/1 HTTP/1.1
DELETE /api/user/1 HTTP/1.1

3)发送未认证错误响应

/*** 发送未认证错误响应*/
private void sendUnauthorizedResponse(HttpServletResponse response, String message) throws IOException {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);String jsonResponse = String.format("{\"code\": 401, \"message\": \"%s\", \"data\": null, \"description\": \"未授权访问\"}",message);response.getWriter().write(jsonResponse);
}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/936524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

环境变量 Path 配置实战指南:从“能用”到“专业”--两种配置环境变量的方法

本指南将通过一个完整的实例,手把手教你如何配置 `Path` 环境变量。我们将超越“如何做”,深入探讨“为什么这么做”,让你彻底理解直接路径与引用路径的本质区别。我们将以配置 Java 开发环境为例,让你清晰地看到每…

10月13日

上午建模语言和数据结构课程 下午听讲Java知识点和练习数据库

Ubuntu22.04安装CH340/CH341驱动

转载自: 陈拓 2024/12/20-2024/12/20 https://zhuanlan.zhihu.com/p/137683332711. 我的系统硬件系统架构arch操作系统版本lsb_release -a2. CH340G,USB-串口转换器3. Ubuntu22.04安装CH340驱动 3.1 用lsusb查看USB插…

玄机蓝队靶场_应急响应_198:实战Live勒索病毒溯源排查

前言: 版权作者:思而听(山东)网络科技有限公司、solar应急响应团队、州弟学安全 特别注意:环境中的勒索家族全版本加密器已被 solar应急响应团队 破解 系统:Windows server 2016 账号密码:administrator/Sierting…

JetBrains Mono字体好看、及其它

请注意箭头。还有输入的是grep != 另外,进到那个深深的目录里后,可以: ln -s `readlink -f .` somewhere 目录不能有hard link,原因可问AI.

STM32——UART

UART通信协议(串口通信) 1、两根通信线(发送和接收),TX与RX要交叉连接。只需进行单向通讯时可只连接一根通信线。 2、仅支持点对点的通信,不像I2C、SPI支持一对多通信。 3、进行通信的两设备电平标准必须一致,当…

WebApi 交叉观察者- IntersectionObserver复盘

交叉观察者- IntersectionObserver复盘 一、 Intersection Observer是什么? Intersection Observer API 提供了一种异步观察目标元素与祖先元素或视口交叉状态的方法。通俗地说,就是可以高效地监测一个元素是否进入或…

[KaibaMath]1009 关于||a|-|b||≤|a+b|的证明

[KaibaMath]1009 关于||a|-|b||≤|a+b|的证明绝对值的三角形不等式为||a|-|b||≤|ab|≤|a|+|b|. 本文给出前半段的证明,即证明||a|-|b||≤|ab|.

css: Bootstrap5 Accordions

<!doctype html> <html> <head> <meta charset="utf-8"> <title>Bootstrap5 Accordions</title><link rel="stylesheet" href="https://cdn.jsdeliv…

AMPopTip - 优雅的iOS动画提示框库

AMPopTip是一个功能丰富的iOS动画提示框库,支持多种弹出方向和箭头样式,可高度自定义颜色、边框和字体,适用于用户引导和界面提示等场景,让应用交互更加生动有趣。AMPopTip AMPopTip 是一个优雅的动画弹出提示框,…

2026年深度对比值得推荐的10个在线客服系统

1. 唯一客服—— 可独立部署的高性能客服系统源码唯一客服系统主要功能是,为网站或APP等提供在线即时聊天功能,可以方便客户与我们的客服人员进行实时沟通的。主要用户群体是中小互联网科技公司,有自己的开发产品,…

文件名中有空格比较烦人

我们已经造好了两个文件:" t.sh"和"t m p" $ " t.sh" "t m p" OK $ " t.sh t m p" # 首先找不到t.sh,其次就算找到,接收到的也是3个参数t, m, p不是一个"t…

十月总结

10.11 广二 T1:计数、容斥原理 有一个计数的做法,大致做法是在最后面的开头统计,然后要求后面不能出现,这样贡献就是唯一的,需要fail树上跑下来dfn这样 容斥原理就比较直接,加上序列中有一个开头的,减去有两个开…

20251013 之所思 - 人生如梦

20251013 之所思1. 前天老板约了一个会议,讨论log的录制,防止问题发生时无法录到现场的数据而反复要求实车同事去复现问题采集数据。当我发言时被另一个同事打断并说表达的不正确,当时很气愤,一是自己刚刚开始发言…

20232421 2024-2025-1 《网络与系统攻防技术》实验一实验报告

20232421 2024-2025-1 《网络与系统攻防技术》实验一实验报告 1.实验目标 本次实践的对象是一个名为pwn1的linux可执行文件。 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。 该程序…

20232317 2025-2026-1《网络与系统攻防技术》实验一实验报告

1.实验内容 1.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。 1.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。 1.3注入一个自己制作的shellcode并运行这段sh…

实用指南:【每日一面】React Hooks闭包陷阱

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Java 面试 - krt

1、ArrayList和LinkedList的区别 2、@Autowired和@Resource的主要区别1、ArrayList和LinkedList的区别 ArrayList:底层数据结构:ArrayList基于数组实现,元素在内存中连续存储,支持随机访问(时间复杂度为o(1));…

软工大三开学总结

在本学期我的目标是主要是在完成本学期的课程目标拿到奖学金的同时跟进考研。 在考虑过很多之后我个人还是觉得考研是我的选择,因为我从心底里觉得,我好不容易 上到这儿了一说是吧,怎么能就止步于此呢,再向上走走呢…