微信静默授权增加浏览器历史记录导致跳转死循环的解决方案

2,641 阅读4分钟
原文链接: www.cnblogs.com

引言

最近做一个微信webapp单页应用项目,项目只需要获取用户的openid;为了更好的用户体验,整个过程让用户无感知,我们采用静默授权的方式来获取openid;具体可以翻看微信开发者文档--微信网页授权部分。

按照微信开发文档的步骤操作,很容易的就实现了获取openid的功能。到此你可能心中窃喜,so easy!如果你认为实现到此结束,那么很可能qa就会找上来,并且还现场给你演示问题来源现场(如下图):

在授权后重定向的回调页面(例如上面例子的下单页面)点击返回,怎么点击都不能返回到正确的页面,一直在这里跳转死循环了,到底该如何解决呢?下面就给出一种实践方案。

跳转死循环的原因

跳转死循环的原因,稍加分析就能知道原因。项目中需要openid的页面会静默获取openid(一般建议在项目入口文件获取,然后缓存起来供其他页面使用);

比方说上面在下单页需要openid,这个时候当进入该页面时,就会重定向到微信获取授权页面:

https://open.weixin.qq.com/connect/oauth2/authorizeappid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

授权成功后会重定向到回调链接地址(上面例子中的下单页),并会带上code参数。我们在实现时是使用location.replace将下单页历史记录替换为微信授权页面。

总的来说,一次授权浏览器历史记录增加了1条记录。那么授权成功后浏览器历史记录到底是怎么样的呢?

理论上,上述过程浏览器历史记录应该是下图所示的结果:

但是经过在微信里面测试,发现并不是这样的,而是如下图所示,怀疑是微信浏览器做了特殊处理。

这样在授权成功后的重定向页面点击微信返回按钮,即上例中从下单页点击返回,会返回到不带code参数的下单页也就是第一次进入时的下单页;然而页面不做特殊处理的话,它会跳转到微信授权页面再次进行授权后又会重定向到指定的回调页面即下单页,这样就会造成跳转死循环的问题,表象上一直停留在下单页,无法进入项目指定的其他页面。

解决方案

通过对整个过程的分析,我们可以知道如果不做任何处理,只是在下单页获取授权后url中携带的code参数,就会出现这种死循环的问题,那么能否在授权页面指定的redirect_uri页面(本例的下单页)做一下处理呢,满足某个条件就不在跳往到微信授权页?

答案当然是可以的,一种实现方案可以是这样的:

  • 指定一个用于授权成功后的回调链接redirect url,域名得和前端业务域名一致,并且整个链接是需要在微信开发者后台配置的。

  • 在进入步骤1指定的页面后,前端需要获取url参数code和sessionStorage中的code值,根据二者code是否均有值来判断是否需要重定向的微信授权页面

  • 在步骤2中两种情况下的code值都为空时,前端使用location.replace(url)方法来跳转到微信授权页面,授权成功后跳转到步骤1指定的回调页面。此时浏览器历史记录只增加了1条,即微信授权页面历史记录

  • 在步骤2设置的回调页面中,若url的code参数有值且sessionStorage获取的code值为null时,将url的code参数值存到sessionStorage中,然后history.back()

  • 在history.back()执行后,就又回到授权链接跳转之前的那个页面,即进入未跳转前的下单页。

  • 再次点击微信返回按钮,就可以正常返回了

具体的代码实现部分如下:

const params = getQueryParams()
const code = sessionStorage.getItem('code')
if (!params.code && !code) {
  let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${yourAppId}&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_base&state=1#wechat_redirect`
   window.location.replace(url)
} else if(!code){
   sessionStorage.setItem('code', params.code)
   history.back()
}

参考