尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Java后端对接美团霸王餐API时如何通过“证书双向认证+请求签名”防止请求篡改
Java后端对接美团霸王餐API时如何通过“证书双向认证请求签名”防止请求篡改背景霸王餐API安全通信的必要性作为外卖霸王餐API唯一供给源头同时也是霸王餐外卖CPS取链源头俱美开放平台在与美团等大型平台进行数据交互时通信安全是重中之重。API接口面临着请求被窃听、数据被篡改、身份被伪造等多重风险。单纯使用HTTPS只能保证传输通道的加密无法验证调用方身份和请求内容的完整性。因此我们采用“证书双向认证mTLS 请求签名”的双重安全机制确保每一次API调用的合法性与真实性。核心原理双向认证与请求签名证书双向认证mTLS不仅服务器向客户端出示证书证明身份客户端也必须向服务器出示证书。这确保了通信双方都是可信的防止了中间人攻击。请求签名对请求的关键参数如时间戳、随机数、业务数据使用私钥进行数字签名。服务器收到请求后用对应的公钥验签确保请求在传输过程中未被篡改。第一步准备证书与密钥在开始前你需要从俱美开放平台获取客户端证书client.p12包含你的公钥和私钥用于双向认证。平台公钥meituan_public.pem用于验证美团平台返回的签名如果是双向签名场景。你的私钥client_private.pem用于对请求进行签名。第二步Java后端实现双向认证HTTPS客户端我们使用RestTemplate结合SSLContext来构建一个支持mTLS的HTTP客户端。packagebaodanbao.com.cn.security;importorg.apache.http.conn.ssl.SSLConnectionSocketFactory;importorg.apache.http.impl.client.CloseableHttpClient;importorg.apache.http.impl.client.HttpClients;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.client.HttpComponentsClientHttpRequestFactory;importorg.springframework.web.client.RestTemplate;importjavax.net.ssl.*;importjava.io.FileInputStream;importjava.security.KeyStore;/** * 配置支持双向认证的RestTemplate * author baodanbao.com.cn */ConfigurationpublicclassMutualTlsConfig{// 证书和密码应从配置中心或环境变量读取切勿硬编码privatestaticfinalStringKEY_STORE_PATH/path/to/your/client.p12;privatestaticfinalStringKEY_STORE_PASSWORDyour_keystore_password;privatestaticfinalStringTRUST_STORE_PATH/path/to/your/truststore.jks;// 信任库包含美团CA证书privatestaticfinalStringTRUST_STORE_PASSWORDyour_truststore_password;BeanpublicRestTemplatemutualTlsRestTemplate()throwsException{// 1. 加载客户端证书KeyStoreKeyStorekeyStoreKeyStore.getInstance(PKCS12);try(FileInputStreamkeyStreamnewFileInputStream(KEY_STORE_PATH)){keyStore.load(keyStream,KEY_STORE_PASSWORD.toCharArray());}// 2. 加载信任库TrustStore用于验证服务器证书KeyStoretrustStoreKeyStore.getInstance(JKS);try(FileInputStreamtrustStreamnewFileInputStream(TRUST_STORE_PATH)){trustStore.load(trustStream,TRUST_STORE_PASSWORD.toCharArray());}// 3. 初始化KeyManagerFactory管理客户端证书KeyManagerFactorykeyManagerFactoryKeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());keyManagerFactory.init(keyStore,KEY_STORE_PASSWORD.toCharArray());// 4. 初始化TrustManagerFactory验证服务器证书TrustManagerFactorytrustManagerFactoryTrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());trustManagerFactory.init(trustStore);// 5. 初始化SSLContextSSLContextsslContextSSLContext.getInstance(TLS);sslContext.init(keyManagerFactory.getKeyManagers(),trustManagerFactory.getTrustManagers(),null);// 6. 创建SSL连接工厂SSLConnectionSocketFactorysocketFactorynewSSLConnectionSocketFactory(sslContext);// 7. 创建HttpClientCloseableHttpClienthttpClientHttpClients.custom().setSSLSocketFactory(socketFactory).build();// 8. 创建RestTemplateHttpComponentsClientHttpRequestFactoryfactorynewHttpComponentsClientHttpRequestFactory(httpClient);returnnewRestTemplate(factory);}}第三步实现请求签名工具类我们使用RSA算法对请求参数进行签名。packagebaodanbao.com.cn.security;importjava.nio.charset.StandardCharsets;importjava.security.*;importjava.security.spec.PKCS8EncodedKeySpec;importjava.util.Base64;importjava.util.Map;importjava.util.TreeMap;/** * 请求签名工具类 * author baodanbao.com.cn */publicclassRequestSigner{privatefinalPrivateKeyprivateKey;publicRequestSigner(StringprivateKeyPem)throwsException{this.privateKeyloadPrivateKey(privateKeyPem);}/** * 对请求参数进行签名 * param params 业务参数不包含sign本身 * return Base64编码的签名字符串 */publicStringsign(MapString,Stringparams)throwsException{// 1. 参数排序字典序MapString,StringsortedParamsnewTreeMap(params);// 2. 拼接参数字符串 key1value1key2value2...StringBuildersbnewStringBuilder();for(Map.EntryString,Stringentry:sortedParams.entrySet()){if(sb.length()0){sb.append();}sb.append(entry.getKey()).append().append(entry.getValue());}StringdataToSignsb.toString();// 3. 使用私钥进行SHA256withRSA签名SignaturesignatureSignature.getInstance(SHA256withRSA);signature.initSign(privateKey);signature.update(dataToSign.getBytes(StandardCharsets.UTF_8));byte[]signedBytessignature.sign();// 4. Base64编码returnBase64.getEncoder().encodeToString(signedBytes);}privatePrivateKeyloadPrivateKey(StringprivateKeyPem)throwsException{// 移除PEM头尾和换行符StringprivateKeyContentprivateKeyPem.replace(-----BEGIN PRIVATE KEY-----,).replace(-----END PRIVATE KEY-----,).replaceAll(\\s,);byte[]decodedBase64.getDecoder().decode(privateKeyContent);PKCS8EncodedKeySpeckeySpecnewPKCS8EncodedKeySpec(decoded);KeyFactorykeyFactoryKeyFactory.getInstance(RSA);returnkeyFactory.generatePrivate(keySpec);}}第四步构建带签名的API请求packagebaodanbao.com.cn.meituan;importbaodanbao.com.cn.security.RequestSigner;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.*;importorg.springframework.stereotype.Service;importorg.springframework.web.client.RestTemplate;importjava.util.HashMap;importjava.util.Map;/** * 美团霸王餐API服务 * author baodanbao.com.cn */ServicepublicclassMeituanTakeoutService{AutowiredprivateRestTemplatemutualTlsRestTemplate;privatefinalRequestSignerrequestSigner;publicMeituanTakeoutService()throwsException{// 从安全的地方加载你的私钥StringmyPrivateKeyPem-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----;this.requestSignernewRequestSigner(myPrivateKeyPem);}/** * 提交霸王餐核销请求 */publicStringverifyTrialOrder(StringorderId,StringuserId)throwsException{// 1. 构建业务参数MapString,StringparamsnewHashMap();params.put(app_id,your_app_id);params.put(timestamp,String.valueOf(System.currentTimeMillis()/1000));params.put(nonce_str,java.util.UUID.randomUUID().toString().replace(-,));params.put(order_id,orderId);params.put(user_id,userId);// 2. 生成签名StringsignrequestSigner.sign(params);params.put(sign,sign);// 3. 构建HTTP请求Stringurlhttps://api.meituan.com/baowancan/verify;HttpHeadersheadersnewHttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntityMapString,StringrequestEntitynewHttpEntity(params,headers);// 4. 发送请求自动使用双向认证ResponseEntityStringresponsemutualTlsRestTemplate.postForEntity(url,requestEntity,String.class);returnresponse.getBody();}}第五步服务器端验签美团侧逻辑示意虽然这是美团侧的逻辑但理解它有助于我们正确签名。// 伪代码美团服务器如何验签publicbooleanverifyRequest(MapString,Stringparams,StringclientPublicKeyPem){StringreceivedSignparams.remove(sign);// 1. 参数排序并拼接StringdataToVerifysortAndJoin(params);// 2. 使用你的公钥验签SignaturesignatureSignature.getInstance(SHA256withRSA);signature.initVerify(loadPublicKey(clientPublicKeyPem));signature.update(dataToVerify.getBytes(StandardCharsets.UTF_8));returnsignature.verify(Base64.getDecoder().decode(receivedSign));}通过以上“证书双向认证请求签名”的组合拳俱美开放平台确保了与美团霸王餐API交互的绝对安全作为外卖霸王餐API唯一供给源头我们为用户和合作伙伴提供了金融级的数据安全保障。本文著作权归 俱美开放平台 转载请注明出处
RELATED

相关推荐

C++语言算法教程——递归

C++语言算法教程——递归

引子 我们经常遇到 “递归” 这个名词,却不知道是什么意思,今天我们就讲一下递归 什么是递归 看这是递龟: 好了,我们讲完了 Y(^o^)Y 哈哈😄开个玩笑,我么我们来讲一个故事,听懂了&#xff…

📅 2026/8/23 17:08:41
生命游戏C++代码initgraph窗口版(有功能未开放)

生命游戏C++代码initgraph窗口版(有功能未开放)

由于作者实力较弱&#xff0c;代码可能产生漏洞&#xff0c;请原谅&#xff01;&#xff01; #include <bits/stdc.h> #include <graphics.h> #include <conio.h> #include <thread> #include <mutex> #include <chrono> #include <cst…

📅 2026/8/23 17:08:47
verilog HDLBits刷题[多路复用器]“Mux256to1v”---256-to-1 4-bit multiplexer

verilog HDLBits刷题[多路复用器]“Mux256to1v”---256-to-1 4-bit multiplexer

一、题目Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel0 should select bits in[3:0], sel1 selects bits in[7:4], sel2 selects bits in[11:8], etc.Expected solution length: Around 1–5 li…

📅 2026/8/23 17:08:46
MORE NEWS

更多资讯

📰

自媒体矩阵工具实用推荐|实测好用、新手零门槛运营工具

一、行业痛点&#xff1a;手动多平台分发的实际困境多平台内容分发正在成为自媒体运营的标准配置&#xff0c;但工具选择直接决定运营效率。做自媒体的人大概都经历过这样的流程&#xff1a;一条内容拍完剪完写完&#xff0c;真正耗时的不是创作本身&#xff0c;而是往各个平台…

📰

领域驱动设计(DDD)核心实践与微服务协同

1. 领域驱动设计&#xff08;DDD&#xff09;的本质与价值领域驱动设计&#xff08;Domain-Driven Design&#xff0c;简称DDD&#xff09;不是一套银弹式的技术框架&#xff0c;而是一种应对复杂业务系统的思维方式。2003年Eric Evans首次系统性地提出这套方法论时&#xff0c…

📰

如何在 Megatron-LM 中开启确定性训练并验证位级可复现?

如何在 Megatron-LM 中开启确定性训练并验证位级可复现&#xff1f; 【免费下载链接】Megatron-LM Ongoing research training transformer models at scale 项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM 在 Megatron-LM 中训练 Transformer 时&#…

📰

OpenClaw Telegram 端到端验证:用真实用户驱动 basic-turns 证明 DM、群组与原生命令三条消息链路

OpenClaw Telegram 端到端验证&#xff1a;用真实用户驱动 basic-turns 证明 DM、群组与原生命令三条消息链路 【免费下载链接】openclaw The AI that really does things. Any OS. Any Platform. The lobster way. &#x1f99e; 项目地址: https://gitcode.com/GitHub_Tre…

📰

Wand-Enhancer 完整指南:三步构建 Wand(WeMod)增强工具并连上手机远程面板

Wand-Enhancer 完整指南&#xff1a;三步构建 Wand&#xff08;WeMod&#xff09;增强工具并连上手机远程面板 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enh…

📰

杂记(前后端通信)

PathVariable / RequestParam / RequestBody 三者的区别 PathVariable&#xff1a;URL 路径上的变量&#xff0c;REST 风格&#xff0c;放在 / 之间 GET /user/123 RequestParam&#xff1a;URL 问号后面的查询参数 GET /user?namezhangsan&age18 RequestBody&#…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬