Lei Zhang

时光已逝永不回,
往事只能回味。
... ...
春风又吹红了花蕊,
你已经也添了新岁。

▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 96%



3Years-9 OAuth2.0授权后将Openid告知于SPA

2018-06-05 » 没填完的坑 / 3Years , Tutorial , Vuejs , 微信开发

项目地址:https://github.com/PassionZale/3Years


许多想在微信公众号开发使用 SPA 架构的开发者,往往第一个拦路虎便是微信的 OAuth2.0 授权登录。

困难之处,或者说是棘手之处便是:服务端获取到 Openid 后如何告知 SPA 应用?

大部分情况下,我所接触过的项目均为 SPA,而非 MPA。经历过数个项目,我自己总结了几个微信授权场景下的前后端处理方式。

以下两种方式,前提条件为前后端项目均在同一个根域之下。


index.html 由服务端渲染

首先大部分开发者应该都明白,每个 SPA 项目都只有一个 HTML 文件,通常为 index.html。

如果你还折腾过服务端的开发,那么你也会知道,每种服务端语言,也都有自己的模板引擎。例如 Java、PHP、Python,它们都有自己的一个或者多个模板引擎。

拿 Laravel 的 .blade.php 模板引擎来讲,在模板引擎中,通过模板引擎所给予的界定符,可以让 HTML、PHP 得到混合编写。只需要服务端获取到 Openid,将其通过混编,赋值给 Javascript 的某个全局变量,这样 SPA 中任意模块或组件都可以从 window 对象中获取到 Openid 。当然不限于 Openid,你还可以根据实际业务需要,存储一些其他的数据,如用户名、邮费、购物车总数等等。

举个简单的例子,有点类似这样:

window.OPENID = "<?php $openid;?>";

和我们将 Laravel 的 csrf_token 放置在 <meta> 标签中如出一辙:

<meta id="csrf-token" content="{{ csrf_token() }}">


index.html 与服务端完全分离

这种情况,便是 3Years 中准备处理的场景。

在这种场景下,我们需要在前端存储 Openid,可以使用许多技术完成该缓存,例如:cookie、localStorage、vuex 等。

由于页面不是由服务端输出的,因此前端自身无法直接拿到 Openid。假设在 vuex 中你存储了 Openid,那么每当 SPA 任意路由首次被访问时,Openid 一定是空。

此时,我们可以在 vue-router 中的钩子函数中,进行一次拦截。拦截只做一件事情:

1. 获取当前的 transition.to.path,并使用 encodeURIComponent 编码,将其作为参数 redirect 传入我们的授权中间路由或组件:Auth.vue;

2. 在 Auth.vue 中,开始读取 cookie,若 Openid 存在,则将 redirect 进行 decodeURIComponent 解码,使用 $router.push() 将当前路由重定向到对应的 redirect 中。

3. 若 Openid 不存在,则拼装链接,让服务端再次发起微信授权,写入 cookie,重定向到 redirect 对应的 SPA 路由。


在 main.js 中加入 vue-router 钩子:


在 Auth.vue 中读取 cookie:


服务端发起微信授权

展开选填信息