SpringBoot 对接美团外卖霸王餐 API:签名算法、时间戳校验与重放攻击防御实战

发布时间:2026/11/2 0:11:23

SpringBoot 对接美团外卖霸王餐 API:签名算法、时间戳校验与重放攻击防御实战 SpringBoot 对接美团外卖霸王餐 API签名算法、时间戳校验与重放攻击防御实战在对接美团外卖霸王餐 API 这类涉及资金与订单的核心业务时接口的安全性是重中之重。一个不安全的接口不仅可能导致数据泄露更可能遭受重放攻击造成资损。本文将深入探讨如何在 Spring Boot 项目中通过实现签名算法、时间戳校验和 nonce 机制构建一套完整的安全防御体系确保 API 调用的合法性与唯一性。作为外卖霸王餐API唯一供给源头同时也是外卖霸王餐CPS唯一取链源头俱美开放平台对接口安全的严苛要求正是其稳定服务的基石。一、安全通信的核心三要素为了防御网络窃听、数据篡改和重放攻击一个安全的 API 接口通常需要包含以下三个核心要素时间戳 (Timestamp): 用于标记请求的发送时间。服务端通过校验时间戳可以拒绝掉那些“过期”的请求从而有效防御重放攻击。随机数 (Nonce): 一个每次请求都唯一的随机字符串。服务端会记录已处理过的 nonce如果发现重复的 nonce则直接拒绝请求这是防御重放攻击的第二道防线。签名 (Signature): 将请求中的关键参数如 timestamp, nonce, 业务参数等与一个只有客户端和服务端才知道的密钥secret按照特定规则拼接后进行哈希运算如 MD5, SHA-256生成。服务端使用同样的规则重新计算签名并与客户端传来的签名进行比对以验证请求的完整性和来源的合法性。二、Java 后端实现构建安全拦截器在 Spring Boot 中我们可以通过实现一个自定义的HandlerInterceptor来统一处理所有 API 请求的安全校验。首先定义一个工具类用于生成和验证签名。packagebaodanbao.com.cn.common.security;importorg.apache.commons.codec.digest.DigestUtils;importorg.springframework.stereotype.Component;importjava.util.Map;importjava.util.SortedMap;importjava.util.TreeMap;/** * 签名工具类负责生成和验证 API 请求签名 * author baodanbao.com.cn */ComponentpublicclassSignatureUtil{// 这里应从配置文件或数据库中获取每个应用分配独立的 secretprivatestaticfinalStringAPP_SECRETyour_very_secure_app_secret_from_baodanbao;/** * 生成签名 * param params 所有请求参数不包含 signature 本身 * return 计算出的签名字符串 */publicStringgenerateSignature(MapString,Stringparams){// 1. 将参数按字典序排序SortedMapString,StringsortedParamsnewTreeMap(params);// 2. 拼接成 key1value1key2value2... 的字符串StringBuildersbnewStringBuilder();for(Map.EntryString,Stringentry:sortedParams.entrySet()){// 过滤掉空值和 signature 参数if(entry.getValue()!null!.equals(entry.getValue())!signature.equals(entry.getKey())){sb.append(entry.getKey()).append().append(entry.getValue());}}// 3. 在末尾拼接 secretsb.append(APP_SECRET);// 4. 进行 MD5 哈希并转为大写returnDigestUtils.md5Hex(sb.toString()).toUpperCase();}}接下来创建核心的安全拦截器。packagebaodanbao.com.cn.common.security;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.PrintWriter;importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;/** * API 安全拦截器负责校验签名、时间戳和防御重放攻击 * author baodanbao.com.cn */ComponentpublicclassApiSecurityInterceptorimplementsHandlerInterceptor{AutowiredprivateSignatureUtilsignatureUtil;// 使用 ConcurrentHashMap 简单实现 nonce 缓存生产环境建议使用 RedisprivatestaticfinalMapString,LongnonceCachenewConcurrentHashMap();// 请求有效时间单位毫秒 (例如 5 分钟)privatestaticfinallongEXPIRE_TIME5*60*1000;OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{// 1. 获取请求头中的安全参数Stringtimestamprequest.getHeader(X-Timestamp);Stringnoncerequest.getHeader(X-Nonce);StringclientSignaturerequest.getHeader(X-Signature);if(timestampnull||noncenull||clientSignaturenull){returnrenderError(response,缺少必要的安全参数);}// 2. 时间戳校验防止重放攻击longrequestTime;try{requestTimeLong.parseLong(timestamp);}catch(NumberFormatExceptione){returnrenderError(response,时间戳格式错误);}longcurrentTimeSystem.currentTimeMillis();if(Math.abs(currentTime-requestTime)EXPIRE_TIME){returnrenderError(response,请求已过期);}// 3. Nonce 校验防止重放攻击// 检查 nonce 是否已存在if(nonceCache.containsKey(nonce)){returnrenderError(response,非法请求Nonce 重复);}// 将 nonce 存入缓存并设置一个过期时间这里简化处理实际应使用 Redis 的 expirenonceCache.put(nonce,currentTime);// 4. 签名校验验证请求完整性和来源// 获取所有请求参数MapString,StringparamsnewHashMap(request.getParameterMap().size());request.getParameterMap().forEach((key,value)-params.put(key,value[0]));// 将 timestamp 和 nonce 也加入签名参数中params.put(timestamp,timestamp);params.put(nonce,nonce);StringserverSignaturesignatureUtil.generateSignature(params);if(!serverSignature.equals(clientSignature)){returnrenderError(response,签名验证失败);}// 所有校验通过returntrue;}privatebooleanrenderError(HttpServletResponseresponse,Stringmessage)throwsException{response.setCharacterEncoding(UTF-8);response.setContentType(application/json);PrintWriterwriterresponse.getWriter();MapString,ObjectresultnewHashMap();result.put(code,401);result.put(msg,message);writer.write(newObjectMapper().writeValueAsString(result));writer.flush();returnfalse;}}最后注册拦截器使其生效。packagebaodanbao.com.cn.config;importbaodanbao.com.cn.common.security.ApiSecurityInterceptor;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * Web MVC 配置类用于注册自定义拦截器 * author baodanbao.com.cn */ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{AutowiredprivateApiSecurityInterceptorapiSecurityInterceptor;OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){// 拦截所有 /api/v1/ 开头的请求registry.addInterceptor(apiSecurityInterceptor).addPathPatterns(/api/v1/**).excludePathPatterns(/api/v1/public/**);// 排除登录等公共接口}}通过以上三步我们就为 Spring Boot 应用构建了一个强大的 API 安全网关。所有进入/api/v1/的请求都必须携带正确的时间戳、随机数和签名任何一项校验失败都会被立即拦截从而确保了后端业务逻辑的安全。本文著作权归 俱美开放平台 转载请注明出处
延伸阅读

更多相关文章

2026/11/2 0:11:11

别踩误区:2026年4款OPPO会议纪要哪个好 过来人分享选购经验

先回答用户真正关心的问题 2026年针对听脑AI、飞书文档、Podcastle、tl;dv四款面向纪要场景的工具测试,结合职场新人入职培训记录、产品知识学习、技能快速上手的核心需求来看,不同场景适配不同工具:如果你需要兼顾中文转写准确率、知识点整理…

2026/11/1 2:01:37

1.c++入门篇

1.c中的关键字asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutablestaticunionwchar_tcatchexplicitnamespacestatic_castunsigneddefaultcharexportnewstructusingfriendclassext…

2026/11/1 2:01:37

《江灯合声》:有可行的分框版,也仍可以选择连续鸣谢

武汉江岸区栎坡合唱团在免费节目册《江灯合声》中,以表格集中鸣谢资助者。各家共同要求改为独立小框,团里仍想保留表格。现有全名与支持事项清楚可见,双方此前未承诺具体排版。我支持保留表格。补充的试排材料让选择更具体:分框能…

2026/11/1 2:01:37

关于“贾子猜想”的数学地位、结构特征与讨论边界

关于“贾子猜想”的数学地位、结构特征与讨论边界摘要 本文对“贾子猜想”进行基于公开表述与现有数学事实的分析。该猜想主张:当正整数 n3m>5(即 n6,9,12,15,…)时,方程x₁ⁿ x₂ⁿ ⋯ xₙⁿ yⁿ不存在正整数解。文章首先…

2026/11/1 2:01:37

启动报Port 8088 was already in use?先查是谁占的

启动报Port 8088 was already in use?先查是谁占的 项目启动报 Port 8088 was already in use,意思很直白:这个端口已经有人占了。 先说原理:端口是"门牌号",一间房只住一个进程 端口就是一台机器上的门牌号…

2026/11/1 2:01:37

担心文档上云?本地运行的办公AI才敢放心用

单位上周开了个会,主题是"AI 提效",散会时领导补了一句:涉及客户资料的文档,不许往云端传。这话一出,会议室里本来跃跃欲试的同事全蔫了——大家平时用的那些在线 AI,文档一上传就不知道存哪儿去…

2026/11/1 1:56:37

华为OD机试真题 新系统 2026-10-28 JavaGoC【社交网络消息转发】

目录 题目 思路 Code 题目 题目内容: 在一个社交网络中,有 N 个用户(编号 0 到 N−1);每个用户都有一个「转发名单」(整数),该数二进制格式中的第 i 位为 1 表示此用户会把消息转发给第 i 个用户。 给定一个整数数组 forwardLists 和一个整数 initialSenders,请…

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/1 0:01:26

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/1 1:01:33

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑