【微前端】记录一次使用react及京东micro-app实现谷歌auth2授权登录的流程 及所遇到的问题排查及最终解决方式

首先,谷歌授权登录需要到google clound上创建一个项目,创建完成后需要创建凭证,之后需要创建web形式的谷歌同意登录屏幕。

背景

我们的项目是建立在electron的基础上搭配micro-app微前端(基座)嵌入各个模块子应用(react脚手架创建的web应用)的搭配模式。

同意按钮使用的第三方插件是react-google-login(用来对接谷歌登录api以及提供统一的登录按钮样式的组件),gapi-script(谷歌的api包)需要初始化。

奇怪的现象

我们的应用是起一个微服务基座对接electron(客户端)的内容,同时再起一个本地子应用服务去实现的谷歌登录按钮(内嵌点击成功和失败回调等api),单独在子应用的服务里加载react-google-login组件按钮,可以正常点击,但是在基座+electron应用服务内(合称桌面客户端)按钮是置灰的,经过多次排查,发现是京东micro-app微前端的沙箱导致的该问题,验证方法是关闭沙箱代理可复现。

定位原因

写了个微前端demo,通过查看发现,点击登录同意按钮后,会自发地异步调用google的多个资源接口,包括字体、JS文件等等。其中有2个js文件是有依赖的,前者的执行依赖后者,且js文件中有多处对window进行了修改,我们知道基座通过proxy代理的方式把全局对象管控了,因此无法直接修改window,与此同时子应用是在沙箱环境中点击的按钮触发请求资源。所以这个时候有依赖的js文件之间获取到的window是undefined,因此报错。

但是我们项目是需要沙箱的,这要怎么办呢?

这边有个前提,我们登录获得同意后,可以拿到部分用户信息例如邮箱、accessToken等信息,这个时候我们还需要通知桌面客户端人员帮我们进行数据处理,他需要拿着这个accessToken去获取谷歌的其他权限。

为了跳过沙箱的限制,我们有以下方案:

1、在桌面端打开一个窗体(electron方式),跳过基座的对子应用的沙箱隔离,这种方式的缺陷是,会导致新开窗体的进程无法被管控,也就是进程无法被kill
2、使用iframe,但是这种方式会丢失全局桥接的对象jsbridge,需要使用类似postMessage消息通知的方式重新获取全局桥接对象
3、采用window.open方式打开一个新的页面(这种方式同样会丢失全局对象,所以需要后续的操作),再以请求或者客户端的协议地址方式进行访问,通知到接口或者协议拦截模块,如果是接口,则创建前端轮询,查到数据就断开链接,关闭轮询。如果是走的客户端协议地址访问的,则由这些拦截模块帮助我们进行调用桌面端特定的方法进行传递用户授权参数给到桌面端的同学。(为什么这么绕呢?因为我们打开的是新的窗体,他不在桌面容器中,没有宿主容器的同时,也缺少全局桥接对象jsbridge,所以我们需要想办法传参给桌面端)。【最终采用的方案】

尝试过但失败的方案:

1、在子应用中以iframe的方式打开授权登录页,但是会导致应用内的token及相关信息无法从容器(基座)注入,导致401授权失败。因此需要先通过跨域postMessage类似的方式将数据传入才能正常展示。
2、子应用直接使用弹窗打开授权登录组件,失败,因为沙箱拦截了google登录所需的网络资源。且因为谷歌授权登录获取资源是自发的请求,我们无法控制,又因为沙箱也是封闭的,通过仅仅暴露出来的escapeProperties无法解决,也不能直接disableSandbox。
3、通过electron的shell.external打开外部客户端默认网页,失败,虽然按钮能被点击,但是无法和容器内的子应用通信,即便传入了全局对象jsbridge也不行,因为运行的宿主环境缺失。
4、通过window.open打开一个独立窗体,情况和第3条一致。

你可能感兴趣的:(前端,react.js,javascript)