开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
现在很多网站都有第三方登录,网页中的微信扫码登录也已经是很常见的功能了,下面就介绍一下网页微信扫码授权登录,咱们前端得如何实现,以及可能遇到的问题和解决方案~
扫码类型
网页中的微信的扫码授权可以分成两种:
-
整体展示:扫码界面
-
这类的会直接跳转到微信官方提供的扫码界面,从url也可以看出来。这中从前端的实现来说是比较容易的一种,但从用户的体验来说并不是很好,本文就不介绍这种了。
-
-
-
局部展示:弹窗扫码
- 这类扫码是以弹窗局部显示,从用户体验来说是比上面一种好的,这种的实现主要是通过iframe,也是后续我介绍的方案。
准备工作
在进行网页微信授权登录接入之前,我们需要在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的 AppID 和AppSecret,申请微信登录且通过审核后,可开始接入流程。官方文档
实现
-
首先我们需要将微信官方提供的JS文件( 文件链接)引入当前页面内
const loadingJSFile = function () { let scriptDom = document.createElement('script'); scriptDom.type = 'text/javascript'; scriptDom.src = 'https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js'; document.body.appendChild(scriptDom); }; loadingJSFile(); -
当我们点击触发弹窗时,首先需要将弹窗绑定的变量设为true,然后再nextTick内来处理展示微信扫码界面, 伪代码如下
import { ref, nextTick } from 'vue'; let isBindWeChat = ref<boolean>(false); const showConfirm = async () => { isBindWeChat.value = true; nextTick(() => { let wxObject = new WxLogin({ id: 'login-div', //展示扫码界面的容器 appid, //应用唯一标识,在微信开放平台提交应用审核通过后获得 scope: 'snsapi_login', //网页应用目前仅填写snsapi_login即可 redirect_uri, //重定向地址, 又公众号配置的回调地址,只能配置一个! state , //用于保持请求和回调的状态,授权请求后原样带回给第三方。 style: 'black',//提供"black"、"white"可选,默认为黑色文字描述 }); } }; showConfirm(); -
至此,唤醒微信扫码授权界面的功能,咱们前端就已经做完了,切图仔的工作就是轻松(手动狗头保命),当然后续扫码成功后的流程需要你们自己与后端配合实现。下图就是唤醒微信扫码的效果:
问题
当你没有问题的时候,问题就来了~
从Chrome 64版本开始,浏览器将阻止任何来自第三方框架的自动重定向。
其他大多数浏览器,默认也是会阻止网页的弹窗和不同域名的重定向功能的:
而我们使用的iframe实现的弹窗扫码授权,就是会重定向网页,当公众号配置的回调地址跟我们当前网页的地址不是同一个域名时,扫码成功后的重定向就会被浏览器默认拦截,导致我们扫码成功后页面没有反应
解决
了解
从实现内展示的图,我们可以知道弹窗是通过iframe的方法嵌入的,因此我们需要去了解一下iframe
iframe默认情况下:采用默认的安全策略。
- iframe的页面将会被当做一个独自的源,同时不能提交表单,以及执行javascript脚本,也不能让包含iframe的父页面导航到其他地方,所有的插件,如flash,applet等也全部不能起作用。
- 简单说iframe就只剩下一个展示的功能,正如他的名字一样,所有的内容都被放入了一个单独的沙盒。
解决的属性
sendbox包含的属性及作用:
- allow-forms 允许进行提交表单
- allow-scripts 运行执行脚本
- allow-same-origin 允许同域请求,比如ajax,storage
- allow-top-navigation 允许iframe能够主导window.top进行页面跳转
- allow-popups 允许iframe中弹出新窗口,比如,window.open,target=”_blank”
- allow-pointer-lock 在iframe中可以锁定鼠标,主要和鼠标锁定有关
iframe默认是没有设置sendbox属性的!因此我们只需要设置上该属性,就可以阻止浏览器默认拦截我们的扫码授权重定向了!!!
以下是伪代码:
let wxObject = new WxLogin({
id: 'login_div',
appid: data.appid,
scope: 'snsapi_login',
redirect_uri: data.redirect_url,
state: data.state,
style: 'black',
href: '',
});
//当new WxLogin后,iframe已经被嵌入到我们指定的id容器内了
let wxIframeEle = document.querySelector('#login-div iframe');
// 对嵌入的微信iframe设置以下属性,可以阻止浏览器默认对重定向的拦截
wxIframeEle.setAttribute(
'sandbox',
'allow-top-navigation allow-same-origin allow-scripts',
);
其他问题
通过上述给微信扫码的iframe设置上sendbox属性后,正常就可以了。
但!
我在开发服测试没问题,不会被浏览器拦截了。可测试一拉一部署,到测试服就G了(哭了~~~)。
于是我立马登录测试服尝试,果然不行...
经过一大堆搜索引擎的搜索链接,最后找到了一个解决办法:在微信生成的iframe的src链接后面拼接上self_redirect=true即可
wxIframeEle.src = `${wxIframeEle.src}&self_redirect=true`;
总结
至此微信扫码授权也算完成了~!
以下是微信文档介绍扫码授权的图例
微信扫码授权流程大致有三,如下:
- 前端向后端拿到公众号的配置数据(亦可写死),唤醒微信扫码弹窗
- 用户扫码成功,微信平台会重定向网页到公众号配置的回调地址(可能是后端的一个接口路径,亦可是前端的一个界面地址)
- 重定向到回调地址的界面或接口后,在这里处理扫码后的逻辑(前后端商量确定如何实现)