thinkjs微信中控之微信鉴权登陆的实现代码


Posted in Javascript onAugust 08, 2019

前言

上一篇文章大概写了一下如何搭一个微信中控服务: 【thinkjs搭建微信中控服务】 。

接下来这篇,专门写一下如何在此基础上扩展出来一个比较好用的微信鉴权登陆的方案。

由于这一段的逻辑着实有点绕,所以就单独拿出来写了。

有时候,调用方甚至可以通过这个方案,进行多公众号openid的之间的关联。

官方说明

开发文档

微信文档地址:传送门

鉴权逻辑

  • 前端跳转到以下url,重定向或者代码跳转都可以:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
  • 弹出是否同意授权的框,用户同意授权(如果是静默授权,就不会弹出同意框),然后页面会重定向到上面链接的redirect_uri地址(一般是开发者处理下一步鉴权逻辑的服务端API),并且会带上code参数。
  • 服务端拿到code之后,调用以下api来获取网页授权的access_token和用户的openid:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

拿到openid之后,理论上鉴权的逻辑就算完成了。

开发者可以继续用openid和access_token去获取用户信息;或者进行一些其他的业务流程。

具体的参数说明看微信的官方文档就可以了。

中控逻辑

第一步:页面跳转至中控API

业务调用方会有自己的登陆逻辑,只需要获取到当前调用接口的用户的openid,然后再进行接下来的业务逻辑即可。

前端调用业务接口的时候,如果服务端发现当前访问用户没有登陆状态,就会告诉前端需要鉴权,并且把需要跳转的中控API链接响应给前端。

然后前端就开始往中控的API链接跳转。

第二步:中控重定向到微信API

相关代码

// 接口 - 鉴权获取code
async go_authAction() {
  let that = this;
  let {back, serve = ''} = that.get();
  if (think.isEmpty(back)) {
    return that.json({code: 1, msg: '参数不正确'})
  }
  let newBack = encodeURIComponent(back);
  let redirectUri = `${baseHost}/api/open/wx/login_wechat?${encodeURIComponent(`back=${newBack}&wxid=${that.wxConfig.id}&serve=${serve}`)}`;
  let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${that.wxConfig.appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
  that.redirect(url);
}

作用:

鉴权获取code

地址:

baseHost + /open/wx/go_auth

参数:

参数名 必选 说明
wxid 对应配置公众号的id,告诉中控用哪个公众号鉴权
back 跳转到鉴权链接之前的页面完整url,便于鉴权完毕后重定向回之前页面
serve 调用方api回调地址,在鉴权逻辑完成后,会携带openid重定向回这个地址

描述:

我这里默认都是静默授权。

在这里可以看到代码里面,中控把调用方传过来的 wxid , back 和 serve 三个参数拼接到了微信API的回调链接 redirect_uri 里面。

第三步:微信回调中控API

相关代码

async login_wechatAction() {
  let that = this;
  let {code, back, serve = ''} = that.get();
  if (think.isEmpty(code) || think.isEmpty(back)) {
    return that.json({code: 1, msg: '参数不正确'})
  }
  let newBack = encodeURIComponent(back);
  let apiWxController = that.controller('private/wx');
  let openid = await that._getOpenIdByAuthCode(that.wxConfig.id, code);
  let backUrl = `${serve}?wxid=${that.wxConfig.id}&openid=${openid}&redirect=${newBack}`;
  that.redirect(backUrl);
}

_getOpenIdByAuthCode(wxid, code){
  let that = this;
  let {appid, secret} = await that.controller('common').getWxConfigById(wxid);
  let {data} = await axios({
    method: 'get',
    url: `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appid}&secret=${secret}&code=$[code]&grant_type=authorization_code`
  })
  return data.openid
}

作用:

通过微信回调传回来的code,获取openid

地址:

baseHost + /open/wx/login_wechat

参数:

参数名 必选 说明
wxid 对应配置公众号的id,告诉中控用哪个公众号鉴权
code 微信回传的code
back 跳转到鉴权链接之前的页面完整url,便于鉴权完毕后重定向回之前页面(上一步拼接的)
serve 调用方api回调地址,在鉴权逻辑完成后,会携带openid重定向回这个地址(上一步拼接的)

描述:

这里中控拿到code之后,去获取openid。 获取完之后,重定向回 serve (业务系统)地址,并把获取到的 openid 和 back 作为参数传回去

第四步:业务系统自行处理

接下来业务系统就能通过开放的回调地址(上面的 serve ),来拿到以下信息:

  • openid (微信ID),
  • redirect (上面的 back ,最初用户在前端调用接口的页面地址)

这时候就能用这个openid去处理自己的登陆逻辑,比如获取用户信息,缓存session保存登陆状态之类的。

然后再重定向回 back 地址,也就是用户在鉴权之前访问的页面。

鉴权结束

简单说就是以下逻辑

  • 前端 调用 业务接口 发现没有登陆状态,告诉前端往中控跳!
  • 前端 跳转至 中控API 拼接接下来要回调的参数
  • 中控 重定向至 微信API 获取code
  • 微信 重定向至 中控API 获取openid
  • 中控 重定向回 业务回调API 拿到openid,保存用户登陆状态
  • 业务 重定向回 前端
  • 前端 调用 业务接口 发现有登陆状态了,完事儿

虽然历经的跳转和重定向看起来很多,但是实际用起来,其实是很快的,用户基本上没有什么感知。

而且对于业务调用方来说,只需要提供一个回调地址即可,然后在回调里面等着openid传过来就好,剩下的交给中控自己去来回蹦哒吧。

结尾

需要注意的是,公众号的后台需要配置好以下信息。

  1. JS接口安全域名:就是前端的访问域名。
  2. 网页授权域名:中控API域名。
  3. ip白名单:中控的ip地址。

否则是没有权限鉴权的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js宝典学习笔记(上)
Jan 10 Javascript
JavaScript 布尔操作符解析  && || !
Aug 10 Javascript
js动态添加表格数据使用insertRow和insertCell实现
May 22 Javascript
jQuery选择器及jquery案例详解(必看)
May 20 Javascript
jQuery向父辈遍历的简单方法
Sep 18 Javascript
详细AngularJs4的图片剪裁组件的实例
Jul 12 Javascript
详解Node.js amqplib 连接 Rabbit MQ最佳实践
Jan 24 Javascript
解决vue 表格table列求和的问题
Nov 06 Javascript
解决Vue打包上线之后部分CSS不生效的问题
Nov 12 Javascript
vue中上传视频或图片或图片和文字一起到后端的解决方法
Dec 01 Javascript
Vue常用的全选/反选的示例代码
Feb 19 Javascript
在HTML5 localStorage中存储对象的示例代码
Apr 21 Javascript
Vue指令之 v-cloak、v-text、v-html实例详解
Aug 08 #Javascript
javascript实现blob加密视频源地址的方法
Aug 08 #Javascript
使用ThinkJs搭建微信中控服务的实现方法
Aug 08 #Javascript
微信小程序云函数使用mysql数据库过程详解
Aug 07 #Javascript
js如何实现元素曝光上报
Aug 07 #Javascript
详解Element-UI中上传的文件前端处理
Aug 07 #Javascript
element-ui中Table表格省市区合并单元格的方法实现
Aug 07 #Javascript
You might like
在PHP的图形函数中显示汉字
2006/10/09 PHP
人大复印资料处理程序_查询篇
2006/10/09 PHP
全世界最小的php网页木马一枚 附PHP木马的防范方法
2009/10/09 PHP
ThinkPHP3.1新特性之命名范围的使用
2014/06/19 PHP
phpExcel中文帮助手册之常用功能指南
2014/08/18 PHP
Ubuntu 11.10 安装Node.js的方法
2011/11/30 Javascript
13 个JavaScript 性能提升技巧分享
2012/07/26 Javascript
WordPress 单页面上一页下一页的实现方法【附代码】
2016/03/10 Javascript
js弹出窗口返回值的简单实例
2016/05/28 Javascript
AngularJS实现与Java Web服务器交互操作示例【附demo源码下载】
2016/11/02 Javascript
js实现页面刷新滚动条位置不变
2016/11/27 Javascript
javascript 面向对象function详解及实例代码
2017/02/28 Javascript
jQuery+CSS3实现点赞功能
2017/03/13 Javascript
vue2.0 父组件给子组件传递数据的方法
2018/01/15 Javascript
vue.js移动数组位置,同时更新视图的方法
2018/03/08 Javascript
微信小程序的mpvue框架快速上手指南
2019/05/15 Javascript
js+canvas实现两张图片合并成一张图片的方法
2019/11/01 Javascript
js实现简单抽奖功能
2020/11/24 Javascript
[01:07]2015国际邀请赛 中国区预选赛精彩回顾
2015/06/15 DOTA
[01:18]PWL开团时刻DAY4——圣剑与抢盾
2020/11/03 DOTA
[54:19]完美世界DOTA2联赛PWL S2 Magma vs PXG 第二场 11.28
2020/12/01 DOTA
python处理xml文件的方法小结
2017/05/02 Python
python 用户交互输入input的4种用法详解
2019/09/24 Python
python根据时间获取周数代码实例
2019/09/30 Python
django实现web接口 python3模拟Post请求方式
2019/11/19 Python
浅谈python已知元素,获取元素索引(numpy,pandas)
2019/11/26 Python
flask框架配置mysql数据库操作详解
2019/11/29 Python
python从zip中删除指定后缀文件(推荐)
2019/12/05 Python
浅谈tensorflow 中tf.concat()的使用
2020/02/07 Python
CLR与IL分别是什么含义
2016/08/23 面试题
创新比赛获奖感言
2014/02/13 职场文书
文体活动总结范文
2014/05/05 职场文书
中学生旷课检讨书模板
2014/10/08 职场文书
优秀教师个人材料
2014/12/15 职场文书
罚站检讨书
2015/01/29 职场文书
SQL Server携程核心系统无感迁移到MySQL实战
2022/06/01 SQL Server