【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端去做请求,因为至少请求是可控的,那么就需要做好回调和沟通的处理。

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

总结

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

相关推荐
bysking17 分钟前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓33 分钟前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_41136 分钟前
无网络安装ionic和运行
前端·npm
理想不理想v37 分钟前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云1 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205871 小时前
web端手机录音
前端
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
神仙别闹1 小时前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
GIS程序媛—椰子2 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js