【Flutter和H5数据传递问题】window.postMessage方法引起的数据问题

Flutter

前言

距离上一篇博客已经过了很长时间了,这次在做公司项目中又遇到了新的问题,决定还是写出来看看各位大神对此有什么看法,分享一下各位的想法。

问题

首先,公司项目的框架是由Flutter去编写的,最初的框架是由uniapp框架来做的,但是uniapp在客户端的性能懂得都懂。。。这里就不过多赘述,所以呢,是从uniapp框架迁移到flutter,但是由于项目周期的原因,最终采取的方式是flutter中混入uniapp,也就是让uniapp以H5的形式混入到flutter代码中,相当于在flutter中打开一个webview,那么就一定会涉及到通信问题。

那么客户端和h5通信有哪些方式呢?

  • nativeApi
  • window.postMessage
  • localStrorage
  • ...

nativeApi:其实就是客户端写一个函数,然后放在全局环境中,让环境中的h5去调用函数,以此来沟通

window.postMessage:这种方式比较常用于客户端向h5端传递数据,然后h5在页面中进行监听,以此获取数据

实际在开发中,方法都是混合使用的,比如我客户端传递数据使用postMessage给h5,h5通过客户端提前在当前环境注入的方法去调用native方法传递数据回给客户端,这种方式都一定是异步的,实际上flutter跟原生层也是异步的,异步肯定就会有延迟。

回到今天的重点问题,就是数据格式的问题,一般来说,客户端传递给h5数据,都会经过jsonEncode一次变成String类型的数据,然后再到h5层进行jsonDecode。

实际代码大致如下:

客户端层:

bash 复制代码
 String data = jsonEncode(result);
 await _controller.evaluateJavascript(
          source: "window.postMessage({data:'$data'},'*')");

h5层:

bash 复制代码
 window.addEventListener('message', (event) => {
		event.data
})

当然,实际上还会更复杂一些,会有一些通信规范和作用范围。

问题是什么呢 ?如果这个数据中存在双引号会怎么样?

双引号问题

可能觉得这种东西没有什么问题,我也大意了没有闪,正常json数据格式大家都很清楚,问题是如果你的数据是用户可以自由输入的,那就涉及格式过滤的问题,比如各种特殊的符号,换行符、制表符等等,这种东西在编码的时候可能没问题,因为但凡能存入数据库的都是处理了的,进行编码都会添加一个反斜杠去处理。

举个例子:

bash 复制代码
//如果你的数据是这样的
//用户的数据的xxxx"
String userData = "xxxxxx""
//那么入库的时候会变成
String userData = "xxxxxx\""

这是为了正确的编码和解码,加上反斜杠到客户端解码的时候会进行转译,最终还是显示一个双引号。

所以你是一对一的,比如客户端------后端,那应该是没问题的,但是如果你的项目是这种后端------客户端------h5端,数据多传一层,可能会遇到这个问题。

当数据到flutter层,flutter有进行了一次编码,此时还是有反斜杠的,但是到h5层会被转译,到h5的时候,此时的json格式就有问题了,变成

bash 复制代码
string aa = "  " " 

双引号和双引号括起来是一段内容,但是后面又多了一个双引号,因为这个内容是用户输入的,用户当然可以随意输入。

问题代码:

bash 复制代码
  String data = jsonEncode(result);
      await _controller.evaluateJavascript(
          source: "window.postMessage({data:'$data'},'*')");

此时data里面的数据还是存在反斜杠的,但是postMessage之后,到h5层反斜杠丢了,json解析失败了。

flutter层如果内容存在反斜杠,decode会被转译,但是encode又会还原回来,这是正确的,没有任何问题。

但是如果传递数据给h5的时候,如果被丢弃掉,就会解析失败,所以我这么处理了:

bash 复制代码
 String data = jsonEncode(result);
      data = data
          .replaceAll(r'\', r'\\') //将单反斜杠替换为双反斜杠
          .replaceAll(RegExp(r"(?<!\\)'"), r"\'"); //将单引号替换为单引号加反斜杠

当然可能还有更好的方法,欢迎在下面留言。

这样哪怕传递过去丢了一个,还会有一个反斜杠,到h5端转译依旧可以成功转译,但是仅限于用户可以自由输入的数据。

比如你如果传递数据是用户数据或者固定格式的数据,你不能这么做,这样会传递错误的数据。

请求数据问题

前面说了,如果你是类似这种混合开发的项目,那么肯定也会有请求数据的问题,当然我们的请求往往也涉及加解密,那么这个请求究竟是放到客户端来做还是h5端来做:

  • 如果是放到客户端来做:

就是h5发起请求通知客户端请求数据,客户端请求数据成功之后再把数据传递回h5端,这种方式如果数据量比较大 的情况,那么性能和效率也比较差 ,当然还涉及到请求没办法落地 的情况,就是h5发起请求,但是突然页面被掐了,请求还在处理但是没办法接收,导致这个请求一直在天上飞,资源释放不了,这是很可怕的事情,意味着请求是不可控的。

  • 请求放到h5端去做

那么客户端就只充当一个加解密的工具,请求可控,但是这里面又涉及异步和延迟的问题

h5端发起请求,将数据丢给客户端去加密回传给h5去请求,响应之后又丢回给客户端去解密后回传给h5,来回总共4次,数据量比较大,实际上性能和效率也会差,甚至如果其中一个环节出问题,可能连回调都没有。

所以这两种方式在数据量比较大的情况,性能都不好,但是呢还是建议在h5端去做请求,因为至少请求是可控的,那么就需要做好回调和沟通的处理。

要想兼顾性能又想兼顾开发周期,这是一件很矛盾的事情,往往都是需要舍弃的,这里就不过多赘述。

总结

千万不要相信用户的任何数据,用户数据是不可信的,一定做好校验和过滤。开发往往都是在舍弃的过程,我们都是在寻求一个平衡的方法。

相关推荐
IT_陈寒2 小时前
Redis内存暴涨,没想到是AOF重写捣的鬼
前端·人工智能·后端
ikoala2 小时前
让 Codex 自己查账:一个省 token 的小技巧
前端·后端·ai编程
ikoala2 小时前
AI 写页面像说明书,修 Bug 像贴膏药?把这两句话写进 AGENTS.md
前端·javascript·ai编程
好的佩奇3 小时前
Dart 之扩展方法
android·flutter·dart
去伪存真4 小时前
AI Agent Harness 深度测评与技术选型实战
前端·agent
好的佩奇5 小时前
蓝牙之经典蓝牙
android·flutter·蓝牙
FRing037 小时前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
传奇开心果编程7 小时前
【Flutter踩坑排雷】第19课:路由硬编码坑|字符串路由书写错误,页面跳转失败排查
android·flutter·ios·移动开发·跨平台·ui框架·声明式ui
疯华整猫10 小时前
被杀掉之后:我把 Android 的「唤起 + 常驻」重做了一遍
前端·面试·架构
IT_陈寒12 小时前
Java开发实战:从入门到精通
前端·人工智能·后端