【Easylive】AppInterceptor和WebAppConfigurer 基于 Token 的请求拦截验证机制

[复制链接]
发表于 2025-5-17 19:23:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
【Easylive】项目常见题目解答(自用&一连更新中…) 汇总版
这两个类共同实现了一个 基于 Token 的请求拦截验证机制,主要用于用户身份认证和权限控制。以下是详细解析:

1. AppInterceptor(核心拦截器类)

类作用

• 实现 HandlerInterceptor 接口,对符合条件的请求举行拦截。
• 主要功能:验证请求中的 Token 是否有效(从 Header 或 Cookie 获取),无效则拒绝访问。
关键代码解析

(1) 成员变量

  1. private static final String URL_ACCOUNT = "/account";
  2. private static final String URL_FILE = "/file";
复制代码
• 作用:定义不需要 Token 验证的白名单路径(如登录、文件公开访问)。
(2) preHandle() 方法(核心逻辑)

  1. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
  2.     // 1. 检查 handler 是否有效
  3.     if (null == handler) {
  4.         return false; // 直接拒绝
  5.     }
  6.    
  7.     // 2. 只处理 HandlerMethod 类型请求(如 @Controller 或 @RestController 定义的处理器方法,Spring 管理的控制器方法)
  8.     if (!(handler instanceof HandlerMethod)) {
  9.         return true; // 其他类型(如静态资源)直接放行
  10.     }
  11.     //Handler type: org.springframework.web.method.HandlerMethod → 控制器方法。
  12.         //Handler type: org.springframework.web.servlet.resource.ResourceHttpRequestHandler → 静态资源
  13.     // 3. 白名单路径放行
  14.     if (request.getRequestURI().contains(URL_ACCOUNT)) {
  15.         return true; // 如登录接口无需 Token
  16.     }
  17.    
  18.     // 4. 获取 Token(优先从 Header,文件请求从 Cookie)
  19.     String token = request.getHeader(Constants.TOKEN_ADMIN);
  20.     if (request.getRequestURI().contains(URL_FILE)) {
  21.         token = getTokenFromCookie(request); // 文件请求特殊处理
  22.     }
  23.    
  24.     // 5. Token 为空或无效时抛出异常
  25.     if (StringTools.isEmpty(token)) {
  26.         throw new BusinessException(ResponseCodeEnum.CODE_901); // Token 缺失
  27.     }
  28.     Object sessionObj = redisComponent.getTokenInfo4Admin(token);
  29.     if (null == sessionObj) {
  30.         throw new BusinessException(ResponseCodeEnum.CODE_901); // Token 无效
  31.     }
  32.    
  33.     return true; // 验证通过
  34. }
复制代码
(3) getTokenFromCookie() 方法

  1. private String getTokenFromCookie(HttpServletRequest request) {
  2.     Cookie[] cookies = request.getCookies();
  3.     if (cookies == null) return null;
  4.     for (Cookie cookie : cookies) {
  5.         if (cookie.getName().equals(Constants.TOKEN_ADMIN)) {
  6.             return cookie.getValue(); // 返回匹配的 Token
  7.         }
  8.     }
  9.     return null;
  10. }
复制代码
• 作用:从 Cookie 中提取 Token(用于文件请求等特别场景)。
(4) 其他方法

• postHandle() 和 afterCompletion():空实现,用于拦截后处置惩罚(如日记记载),当前未利用。

2. WebAppConfigurer(拦截器配置类)

类作用

• 实现 WebMvcConfigurer 接口,注册拦截器并配置拦截规则。
• 核心功能:将 AppInterceptor 应用到所有请求路径(/**)。
关键代码解析

  1. @Configuration
  2. public class WebAppConfigurer implements WebMvcConfigurer {
  3.     @Resource
  4.     private AppInterceptor appInterceptor; // 注入拦截器
  5.     @Override
  6.     public void addInterceptors(InterceptorRegistry registry) {
  7.         registry.addInterceptor(appInterceptor)
  8.                .addPathPatterns("/**"); // 拦截所有路径
  9.     }
  10. }
复制代码
• addPathPatterns("/**"):
表现拦截所有请求(可通过 excludePathPatterns() 清除特定路径,如 /api/public/**)。

3. 协作流程


  • 请求到达 Spring MVC
    • 先经过 WebAppConfigurer 注册的 AppInterceptor。
  • 拦截器验证逻辑
    • 白名单放行:如 /account/login 直接通过。
    • Token 查抄:
    ◦ 普通请求从 Header 的 TOKEN_ADMIN 获取 Token。
    ◦ 文件请求(/file/**)从 Cookie 获取 Token。
    • Redis 验证:查抄 Token 是否有效(如是否过期或被踢出)。
  • 验证结果处置惩罚
    • 成功:继续执行后续拦截器或 Controller。
    • 失败:抛出 BusinessException(最终会被全局非常处置惩罚器转换为错误响应)。

4. 计划亮点


  • 灵活 Token 获取
    • 支持 Header 和 Cookie 两种方式,顺应差别场景(如 API 调用和浏览器文件下载)。
  • 白名单机制
    • 公开接口(如登录)无需 Token,制止循环验证。
  • Redis 集中管理
    • Token 状态(如有效期、强制失效)由 Redis 控制,实现分布式会话。

5. 典型应用场景

• 用户登录态校验:
访问 /admin/* 时要求携带有效 Token。
• 文件安全下载:
文件接口(/file/*)通过 Cookie 通报 Token,确保只有登录用户可访问。
• 权限控制扩展:
可在 preHandle() 中进一步查抄用户角色(如从 sessionObj 解析权限)。

总结

类名职责核心方法AppInterceptor拦截请求并验证 TokenpreHandle()WebAppConfigurer注册拦截器到 Spring MVCaddInterceptors() 通过这两个类,系统实现了 统一、可扩展的认证层,确保只有合法请求能访问受掩护资源。
为什么文件请求和其他请求分开处置惩罚 Token 的获取方式?

1. 技术限制:浏览器对文件请求的 Header 处置惩罚

(1) 普通 API 请求(利用 Header 通报 Token)



  • 场景:前后端分离架构中,前端(如 Vue/React)通过 AJAX/Fetch 调用 API。
  • Token 通报方式:
    通过 HTTP 请求头(如 Authorization: Bearer  或自定义头 TOKEN_ADMIN)通报。

上风
:


  • 安全性高:Header 不会被浏览器主动缓存或记载在日记中。
  • 得当 RESTful API:符合无状态认证的最佳实践。
(2) 文件请求(利用 Cookie 通报 Token)



  • 场景:浏览器直接访问文件下载链接(如 []() 或 ``)。
  • 题目:
    浏览器在发起非 AJAX 的文件请求​(如直接访问 URL、、 标签)时:

    • 无法自定义 Header:浏览器不会允许通过普通 HTML 标签或跳转设置自定义头。
    • 主动携带 Cookie:浏览器会主动在请求中附加当前域的 Cookie(如果 Cookie 的 Path 和 Domain 匹配)。

  • 解决方案:
    对于文件请求,改用 ​Cookie 通报 Token,由于:

    • 浏览器会主动管理 Cookie 的发送。
    • 无需前端代码显式设置 Header。

4. 实际应用场景示例

(1) 普通 API 请求

javascript
复制
  1. // 前端调用 API(可自定义 Header)
  2. fetch("/api/data", {
  3.     headers: { "TOKEN_ADMIN": "xyz123" }
  4. });
复制代码
服务端:从 Header 提取 Token。
(2) 文件下载请求

html
运行
复制
  1. <!-- 浏览器直接访问文件链接 -->
  2. <a href="/file/123.pdf">下载PDF</a>
  3. <!-- 或图片加载 -->
  4. <img src="/file/456.jpg">
复制代码
服务端:从 Cookie 提取 Token(由于浏览器不会为这些请求设置自定义 Header)。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表