《历史代码分析》1、接口安全校验-拦截器的使用

news/2025/3/4 17:39:52/文章来源:https://www.cnblogs.com/loveyous/p/18746640

1、接口安全校验-拦截器的使用

20250302192623655366.png

本系列《历史代码分析》为工作中遇到具有代表性的代码,已做脱敏处理。今天我们讲一下接口安全检验,使用到Spring中的拦截器。

请先看下面代码:

package tech.xueyao.filter.interceptor;import tech.xueyao.contant.properties.SystemProperties;
import tech.xueyao.exception.NoPermissionException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;/*** @Note:* @auther: Simon.Xue* @create: 2019/11/8 12:07*/
@Component
public class CheckSignInterceptor implements HandlerInterceptor {private static Logger logger = LoggerFactory.getLogger(CheckSignInterceptor.class);@Autowiredprivate SystemProperties systemProperties;@Overridepublic void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,Exception arg3) throws Exception {}@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,ModelAndView arg3) throws Exception {}@Overridepublic boolean preHandle(HttpServletRequest req, HttpServletResponse response, Object object)throws Exception {String token = req.getHeader("token");String current_timestamp = req.getHeader("current-timestamp");String nonce_str = req.getHeader("nonce-str");String sign = req.getHeader("sign");logger.debug("token = {}, current_timestamp = {}, nonce_str = {}, sign = {}", token, current_timestamp, nonce_str, sign);if (StringUtils.isEmpty(current_timestamp)|| current_timestamp.length() != 13|| StringUtils.isEmpty(nonce_str)|| nonce_str.length() < 16|| StringUtils.isEmpty(sign)) {//返回调用方,没有接口权限logger.error("返回调用方信息:没有接口权限");throw new NoPermissionException("没有接口访问权限");}// 验证sign签名String apiSecurityKey = systemProperties.getSecurity().getMd5ValidKey();token = StringUtils.isEmpty(token) ? "" : token;String waitSignStr =token + current_timestamp.substring(0, 10) + nonce_str.substring(0, 16) + apiSecurityKey;String mySign = DigestUtils.md5Hex(waitSignStr);if (!mySign.equalsIgnoreCase(sign)) {logger.error("调用接口时,验证签名:不一致");throw new NoPermissionException("签名不一致");}return true;}
}

以下是对这段 Java 代码的分析:

1. 代码概述

这段代码定义了一个名为CheckSignInterceptor​的拦截器,它实现了 Spring 的HandlerInterceptor​接口。该拦截器的主要功能是在处理 HTTP 请求之前,对请求头中的签名信息进行验证,以确保请求具有合法的访问权限。

这段代码是定义一个拦截器,实现了HandlerInterceptor​接口,主要是在处理HTTP请求之前,对请求头的中签名信息进行校验,只有检验通过,才能访问接口。注意,肯定有不需要检验的接口,如登录功能,所以需要配置忽略拦截路径,本文不介绍。

2. 类定义和注解

@Component
public class CheckSignInterceptor implements HandlerInterceptor {
  • @Component​:这是 Spring 的注解,说明该类为一个组件,程序启动时,Spring会自己扫描管理它。
  • implements HandlerInterceptor​,需要实现接口中的三个方法。

3. HandlerInterceptor​方法实现

afterCompletion​方法,该方法在接口请求完成后调用。

postHandle​方法,该方法在接口请求后、视图渲染之前调用。

preHandle​方法,该方法在接口请求前调用,因为我们需要判断是否有权限访问接口,所以我们要在之前做校验判断。

@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse response, Object object)throws Exception {String token = req.getHeader("token");String current_timestamp = req.getHeader("current-timestamp");String nonce_str = req.getHeader("nonce-str");String sign = req.getHeader("sign");logger.debug("token = {}, current_timestamp = {}, nonce_str = {}, sign = {}", token, current_timestamp, nonce_str, sign);if (StringUtils.isEmpty(current_timestamp)|| current_timestamp.length() != 13|| StringUtils.isEmpty(nonce_str)|| nonce_str.length() < 16|| StringUtils.isEmpty(sign)) {//返回调用方,没有接口权限logger.error("返回调用方信息:没有接口权限");throw new NoPermissionException("没有接口访问权限");}// 验证sign签名String apiSecurityKey = systemProperties.getSecurity().getMd5ValidKey();token = StringUtils.isEmpty(token) ? "" : token;String waitSignStr =token + current_timestamp.substring(0, 10) + nonce_str.substring(0, 16) + apiSecurityKey;String mySign = DigestUtils.md5Hex(waitSignStr);if (!mySign.equalsIgnoreCase(sign)) {logger.error("调用接口时,验证签名:不一致");throw new NoPermissionException("签名不一致");}return true;
}

上面代码步骤

  1. 从请求头中获取token​、current-timestamp​、nonce-str​和sign​信息。
  2. 检查请求头信息,如果current-timestamp​为空或长度不为 13,nonce-str​为空或长度小于 16,sign​为空,则抛出NoPermissionException​异常,代表没有接口权限。
  3. 从配置类SystemProperties​中获取加密密钥getMd5ValidKey,​此密钥为固定的常量。
  4. 根据事先指定签名的规则,拼接字符串waitSignStr​,并使用 MD5 算法生成最终的签名mySign​。
  5. 用生成的签名mySign​和请求头中的传来的签名sign​比较,如果不一致,则抛出NoPermissionException​异常,代表没有接口权限。
  6. 如果所有校验都通过,则返回true​,代表有接口权限,继续执行业务代码。

6. 总结

在不同的公司中,我都看到相似的业务逻辑,都会对接口做一些签名校验,本篇文章中,每次都要计算签名,这种方法并不很好,建议把生成的签名信息放在Redis缓存中,这是现在比较流行的做法。

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

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

相关文章

Anaconda安装指南(conda 不是内部或外部命令,也不是可运行的程序 或批处理文件)

原文链接:https://zhuanlan.zhihu.com/p/101434455 第一步:附上软件下载链接,自行下载 以下是Anaconda的下载链接及相关信息: 官方下载链接Anaconda官网下载地址:https://www.anaconda.com/products/distribution。Anaconda中文官网下载地址:https://www.anacondacn.com/…

docker-compose本地部署前后端分离的项目

本文使用docker-compose进行容器化部署前后端分离的项目(前端vue、后端springboot),部署的虚拟机是centOS系统1.准备打包项目 使用maven打包springboot项目为.jar文件得到springboot-0.0.1-SNAPSHOT.jar打包vue项目 npm install -g @vue/cli安装Vue CLI 在项目根目录下,运行…

使用云效实现流水线部署前后端分离的项目

使用云效实现流水线部署前后端分离的项目1.流水线远程自动化部署 1.1核心代码准备 使用git add .,git commit,git push将本地部署项目中的文档上传到远端仓库(新建的docker12)代码已上传成功修改Dockerfile有关镜像部分,使用阿里云容器镜像服务制品中心的base镜像。 jdk镜…

2.1 TCP/IP网络模型

不同设备的进程间通信,需要网络通信。 又设备多样,需要兼容,协商出来了网络协议。 应用层:专注为用户提供应用功能,如HTTP、FTP、Telnet、DNS等 工作在 用户态。 传输层:为应用层提供网络支持。(数据传输媒介) 传输协议:TCP和UDP。 网络层:实际的传输功能。 常用IP协…

关于flex布局

1.flex初探 简单示例 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>.menu {border: 1px solid red;width: 500px;display: flex;}.menu .item{width: 45px;heigh…

构建窗体--java进阶day03

1.窗体对象Jframe 要创建窗体就需要Jframe对象,窗体创建好不会自己显示,还需要我们自己写一段代码让其显示2.设置窗体可见--setVisible(true) 该方法用于显示窗体3.窗体大小调节--setSize() 该方法用于调节窗体的大小,如下图宽(左到右)500,长(上到下)8004.修改窗体…

私藏!程序员必备的 6 款画图工具,工作效率直线飙升!

宝子们,日常工作里,画图可是个高频需求,不管是梳理思路、设计架构,还是给团队讲解方案,都离不开各种图形。今天我就把私藏多年的6款画图工具分享给大家,每一款都超实用,能帮咱高效搞定各类图形绘制工作! 一、Draw.io:功能强大的绘图宝藏 Draw.io堪称免费绘图工具里的…

[Webpack] 打包优化 一

代码准备 由于需要演示webpack的一些优化处理,因此代码提前做了一些处理,引入了vue-router路由,创建了几个view页面 引入了element-plus,axios,echarts,vue-echarts,@vueuse等组件丰富页面展示 引入了unplugin-vue-components,unplugin-auto-import等处理element-plus的…

[Esbuild] 自定义插件

esbuild自定义插件 插件开发其实就是基于原有的体系结构中进行扩展和自定义。 Esbuild 插件也不例外,通过 Esbuild 插件我们可以扩展 Esbuild 原有的路径解析、模块加载等方面的能力,并在 Esbuild 的构建过程中执行一系列自定义的逻辑。 esbuild 插件是一个带有name和setup函…

ASP.NET Core 3框架揭秘 10

IHostBuilder  IHost  IHostService  IHostApplicationLifetimeWebApplication ==> createbuilder创建了一个新的new WebApplicationBuilder。 WebApplicationBuilder里的初始话方法中,首先会创建一个HostApplicationBuilder对象,HostApplicationBuilder主要用于表示…

Vitepress+EdgeOne Pages快速迁移旧网站内容

本文详细记录使用Vitepress+腾讯云EdgeOne Pages迁移旧网站内容的过程。Vitepress+EdgeOne Pages快速迁移旧网站内容 目录Vitepress+EdgeOne Pages快速迁移旧网站内容下载旧网站文章、图片网站文章转MarkdownVitepress项目快速开始EdgeOne Pages零帧起手参考材料 去年在阿里云码…

记录:tinyrenderer

Bresenham’s line drawing(布雷森汉姆算法) 进行games101的光栅化作业时,对其渲染原理仍不甚了解,找到tinyrenderer软光栅项目。在此记录下试错的过程。 作者在最初为我们做好了framebuffer,读者入手的方向实际是从渲染的过程开始。对于如何渲染出像素显示在画面上,应该需…