news 2026/6/4 13:34:01

HarmonyOS6.1实战:网络层迁移与MD5签名认证方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS6.1实战:网络层迁移与MD5签名认证方案

一、背景

1.1 Android端网络层

Android应用使用OkHttp + Retrofit,服务端API需要MD5签名认证。

1.2 迁移挑战

  • HarmonyOS没有直接的OkHttp对应物
  • 需要使用@kit.NetworkKit的http模块
  • MD5签名需要使用@kit.CryptoArchitectureKit
  • Cookie管理机制不同

二、API签名机制

2.1 签名规则

签名字符串构成:

signSource = APP_KEY + APP_SECRET + queryString + request_time sign = MD5(signSource)

最终URL:

finalUrl = baseUrl + "?" + queryString + "&sign=" + sign

2.2 Android端实现

// Android端MD5实现publicstaticStringmd5(Stringtext){try{MessageDigestmd=MessageDigest.getInstance("MD5");byte[]bytes=md.digest(text.getBytes());StringBuildersb=newStringBuilder();for(byteb:bytes){sb.append(String.format("%02x",b));}returnsb.toString();}catch(Exceptione){return"";}}// 构建签名URLStringqueryString="request_time="+requestTime+"&app_key="+APP_KEY+"&client=android";StringsignSource=APP_KEY+APP_SECRET+queryString+requestTime;Stringsign=md5(signSource);StringfinalUrl=baseUrl+"?"+queryString+"&sign="+sign;

三、HarmonyOS网络层实现

3.1 MD5签名实现

import{cryptoFramework}from'@kit.CryptoArchitectureKit'import{util}from'@kit.ArkTS'exportclassUrlDef{privatestaticAPP_KEY:string='1c218829f927e2cae8ef6bdc0ca3a090'privatestaticAPP_SECRET:string='70b37149b3276009a0b0eb643a316e00'// MD5哈希privatestaticasyncmd5(text:string):Promise<string>{// 创建MD5实例constmd=cryptoFramework.createMd('MD5')// 文本转字节constdata:Uint8Array=newutil.TextEncoder().encodeInto(text)// 更新数据awaitmd.update({data:data})// 计算哈希constresult:cryptoFramework.DataBlob=awaitmd.digest()// 转换为十六进制字符串consthexString=Array.from(result.data).map((byte:number)=>{returnbyte.toString(16).padStart(2,'0')}).join('')returnhexString}}

关键点:

  • 使用cryptoFramework.createMd('MD5')创建MD5实例
  • TextEncoder().encodeInto()将字符串转为Uint8Array
  • md.update()更新数据
  • md.digest()计算哈希
  • 转换为小写十六进制字符串(padStart(2, '0')

3.2 URL构建

privatestaticasyncbuildAuthUrl(baseUrl:string,extraParams?:Record<string,string>):Promise<string>{constrequestTime=Math.floor(Date.now()/1000).toString()// 构建查询字符串(按照Android端的顺序)constqueryParts:string[]=[]queryParts.push(`request_time=${requestTime}`)queryParts.push(`app_key=${UrlDef.APP_KEY}`)queryParts.push(`client=android`)// 添加额外参数if(extraParams){constkeys=Object.keys(extraParams)for(leti=0;i<keys.length;i++){constkey=keys[i]queryParts.push(`${key}=${encodeURIComponent(extraParams[key])}`)}}constqueryString=queryParts.join('&')// 构建签名源字符串constsignSource=`${UrlDef.APP_KEY}${UrlDef.APP_SECRET}${queryString}${requestTime}`// 计算签名constsign=awaitUrlDef.md5(signSource)// 最终URLconstfinalUrl=`${baseUrl}?${queryString}&sign=${sign}`returnfinalUrl}

注意事项:

  1. 参数顺序必须与Android端一致
  2. encodeURIComponent()编码特殊字符
  3. 签名源字符串格式严格遵守:APP_KEY + APP_SECRET + queryString + request_time

3.3 API定义

// 登录接口staticasynclogin():Promise<string>{returnawaitUrlDef.buildAuthUrl(UrlDef.getFinalHost()+'login_do')}// 获取最佳服务器staticasyncopenHomeBest(appCateId:string):Promise<string>{constparams:Record<string,string>={}asRecord<string,string>params['app_cate_id']=appCateId params['request_time']=Math.floor(Date.now()/1000).toString()params['session_id']='harmonyos_session'returnawaitUrlDef.buildAuthUrl(UrlDef.getFinalHost()+'home/best',params)}// 启动应用staticasynchomeStart(streamId:string):Promise<string>{constparams:Record<string,string>={}asRecord<string,string>params['streamer_id']=streamIdreturnawaitUrlDef.buildAuthUrl(UrlDef.getFinalHost()+'home/start',params)}

四、HTTP客户端实现

4.1 HttpClient封装

import{http}from'@kit.NetworkKit'exportclassHttpClient{privatestaticinstance:HttpClientprivatecookie:string=''staticgetInstance():HttpClient{if(!HttpClient.instance){HttpClient.instance=newHttpClient()}returnHttpClient.instance}setCookie(cookie:string):void{this.cookie=cookieconsole.log('[HttpClient] Cookie set:',cookie)}getCookie():string{returnthis.cookie}asyncget(url:string):Promise<string>{returnnewPromise((resolve,reject)=>{constrequest=http.createHttp()constoptions:http.HttpRequestOptions={method:http.RequestMethod.GET,header:{'Content-Type':'application/json','Cookie':this.cookie},connectTimeout:60000,readTimeout:60000}console.log('[HttpClient] GET:',url)console.log('[HttpClient] Cookie:',this.cookie)request.request(url,options,(err,data)=>{if(!err){// 保存Cookieif(data.header&&data.header['set-cookie']){constsetCookie=data.header['set-cookie']asstringthis.cookie=setCookieconsole.log('[HttpClient] Received Cookie:',setCookie)}constresult=data.resultasstringresolve(result)}else{console.error('[HttpClient] Error:',err.message)reject(newError(err.message))}request.destroy()})})}asyncpost(url:string,body:object):Promise<string>{returnnewPromise((resolve,reject)=>{constrequest=http.createHttp()constoptions:http.HttpRequestOptions={method:http.RequestMethod.POST,header:{'Content-Type':'application/json','Cookie':this.cookie},extraData:JSON.stringify(body),connectTimeout:60000,readTimeout:60000}console.log('[HttpClient] POST:',url)console.log('[HttpClient] Body:',JSON.stringify(body))request.request(url,options,(err,data)=>{if(!err){// 保存Cookieif(data.header&&data.header['set-cookie']){constsetCookie=data.header['set-cookie']asstringthis.cookie=setCookie}constresult=data.resultasstringresolve(result)}else{reject(newError(err.message))}request.destroy()})})}}

关键点:

  • 单例模式管理HttpClient
  • 自动保存和发送Cookie
  • 统一的错误处理
  • 超时配置

4.2 使用示例

import{HttpClient}from'../network/HttpClient'import{UrlDef}from'../network/UrlDef'// 获取HttpClient实例consthttpClient=HttpClient.getInstance()// 登录constloginUrl=awaitUrlDef.login()constloginBody={username:'user',password:'pass',verify_code:'code'}constresponse=awaithttpClient.post(loginUrl,loginBody)// 获取应用列表(自动带Cookie)constappListUrl=awaitUrlDef.homeAppList()constappList=awaithttpClient.get(appListUrl)

五、常见问题

5.1 签名验证失败

错误:服务端返回"签名错误"

原因:

  1. 参数顺序不一致
  2. MD5计算错误
  3. URL编码问题
  4. 时间戳格式错误

调试方法:

console.log('[UrlDef] baseUrl:',baseUrl)console.log('[UrlDef] queryString:',queryString)console.log('[UrlDef] signSource:',signSource)console.log('[UrlDef] sign:',sign)console.log('[UrlDef] finalUrl:',finalUrl)

对比Android端日志,确保:

  • queryString完全一致
  • signSource完全一致
  • sign完全一致

5.2 API路径错误

错误:“资源不存在”(code 50016)

原因:HarmonyOS使用了错误的API路径

示例:

// ❌ 错误 - 多了'open/'前缀awaitUrlDef.buildAuthUrl(UrlDef.getFinalHost()+'open/home/best',params)// ✅ 正确awaitUrlDef.buildAuthUrl(UrlDef.getFinalHost()+'home/best',params)

解决方案:
参考Android端的API路径定义,确保完全一致。

5.3 Cookie丢失

现象:登录后的请求返回"未登录"

原因:Cookie未正确保存或发送

解决:

// 检查Cookie是否保存console.log('[HttpClient] Current cookie:',this.cookie)// 确保每次请求都带Cookieheader:{'Cookie':this.cookie}// 检查服务端返回的set-cookieif(data.header&&data.header['set-cookie']){constsetCookie=data.header['set-cookie']asstringthis.cookie=setCookie}

六、与Android对比

特性AndroidHarmonyOS
HTTP库OkHttp@kit.NetworkKit
MD5库MessageDigestCryptoArchitectureKit
文本编码getBytes()TextEncoder
字节转十六进制String.format(“%02x”)toString(16).padStart(2, ‘0’)
Cookie管理自动手动保存和发送
异步模式回调/RxJavaPromise/async-await

七、最佳实践

7.1 统一错误处理

interfaceApiResponse<T>{code:numbermessage?:stringresult?:T}asyncfunctioncallApi<T>(url:string):Promise<T>{constresponse=awaithttpClient.get(url)constresult=JSON.parse(response)asApiResponse<T>if(result.code!==0){thrownewError(result.message||'请求失败')}if(!result.result){thrownewError('返回数据为空')}returnresult.result}

7.2 请求超时重试

asyncfunctionretryRequest(url:string,maxRetries:number=3):Promise<string>{for(leti=0;i<maxRetries;i++){try{returnawaithttpClient.get(url)}catch(e){if(i===maxRetries-1){throwe}awaitnewPromise(resolve=>setTimeout(resolve,1000*(i+1)))}}thrownewError('Max retries exceeded')}

7.3 日志脱敏

functionlogUrl(url:string){// 隐藏敏感参数constsanitized=url.replace(/sign=[^&]+/,'sign=***').replace(/token=[^&]+/,'token=***')console.log('[API]',sanitized)}

八、总结

HarmonyOS网络层迁移的关键点:

  1. MD5签名:使用CryptoArchitectureKit,确保与Android端结果一致
  2. 参数顺序:严格遵守Android端的参数顺序
  3. Cookie管理:手动保存和发送,不像OkHttp自动处理
  4. 异步编程:使用Promise和async/await替代回调
  5. API路径:确保与Android端完全一致

完成网络层迁移后,应用可以正常与服务端通信,进行登录、获取应用列表、启动云桌面等操作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 13:31:18

别再分开优化了!用MATLAB遗传算法搞定选址+配送路径规划(LRP问题实战)

用MATLAB遗传算法实现选址与配送路径的协同优化 想象一下&#xff0c;你负责一家新兴电商公司的物流网络设计。传统做法是先选定仓库位置&#xff0c;再规划配送路线——但这种分步优化往往导致总成本居高不下。选址-路径问题(LRP)的突破性在于&#xff0c;它将两个决策环节融为…

作者头像 李华
网站建设 2026/6/4 13:30:31

如何识破AI虚假模型宣传:GPT-5.5不存在的硬核验证法

我必须明确指出&#xff1a;OpenAI从未发布过名为“GPT-5.5”的模型&#xff0c;也未在2026年4月23日或任何时间点推出所谓GPT-5系列&#xff08;包括GPT-5.2、GPT-5.4、GPT-5.5&#xff09;的任何版本。截至2024年7月&#xff0c;OpenAI官方公开发布的最先进通用大语言模型是G…

作者头像 李华
网站建设 2026/6/4 13:29:49

用Wireshark抓包实战:一步步拆解QQ邮箱POP3登录与收信全过程

用Wireshark抓包实战&#xff1a;一步步拆解QQ邮箱POP3登录与收信全过程当你打开邮箱客户端收取邮件时&#xff0c;背后其实隐藏着一场精密的网络对话。作为网络安全初学者&#xff0c;理解这些底层协议的工作原理&#xff0c;不仅能提升排错能力&#xff0c;更能培养真正的协议…

作者头像 李华
网站建设 2026/6/4 13:27:25

2026 网安零基础进阶指南,完整学习路线助力低成本技术翻身

网络安全作为数字时代的核心刚需领域&#xff0c;岗位需求持续激增&#xff0c;薪资水平稳居行业前列。但很多零基础学习者入门时会陷入资料杂乱、方向迷茫、学用脱节的困境——要么盲目刷课却不懂实战&#xff0c;要么只学工具却缺乏底层逻辑。 本文整理了一套循序渐进、实战…

作者头像 李华
网站建设 2026/6/4 13:27:18

如何在ARM设备上快速运行Windows程序:Box64终极指南

如何在ARM设备上快速运行Windows程序&#xff1a;Box64终极指南 【免费下载链接】box64 Box64 - Linux Userspace x86_64 Emulator with a twist, targeted at ARM64, RV64 and LoongArch Linux devices 项目地址: https://gitcode.com/gh_mirrors/bo/box64 还在为ARM设…

作者头像 李华