微信小程序中做用户登录与登录态维护的实现详解


Posted in Javascript onMay 17, 2017

总结

大家都知道,在开发中提供用户登录以及维护用户的登录状态,是一个拥有用户系统的软件应用普遍需要做的事情。像微信这样的一个社交平台,如果做一个小程序应用,我们可能很少会去做一个完全脱离和舍弃连接用户信息的纯工具软件。

让用户登录,标识用户和获取用户信息,以用户为核心提供服务,是大部分小程序都会做的事情。我们今天就来了解下在小程序中,如何做用户登录,以及如何去维护这个登录后的会话(Session)状态。下面来看看详细的介绍:

在微信小程序中,我们大致会涉及到以下三类登录方式:

  • 自有的账号注册和登录
  • 使用其他第三方平台账号登录
  • 使用微信账号登录(即直接使用当前已登录的微信账号来作为小程序的用户进行登录)

第一和第二种方式是目前Web应用中最常见的两种方式,在微信小程序中同样可以使用,但是需要值的注意的是,小程序中没有Cookie的机制,所以在使用这2种方式前,请确认你们或第三方的API是否需要依赖Cookie;还有小程序中也不支持HTML页面,那些需要使用页面重定向来进行登录的第三方API就需要改造,或不能用了。

我们今天主要来讨论一下第三种方式,即如何使用微信账号进行登录,因为这种方式和微信平台结合最紧密,用户体验比较好。

登录流程

引用小程序官方文档的登录流程图,整个登录流程基本如下图所示:

微信小程序中做用户登录与登录态维护的实现详解
登录流程图

该图中,“小程序”指的就是我们使用小程序框架写的代码部分,“第三方服务器”一般就是我们自己的后台服务程序,“微信服务器”是微信官方的API服务器。

下面我们来逐步分解一下这个流程图。

步骤1:在客户端获取当前登录微信用户的登录凭证(code)

在小程序中登录的第一步,就是先获取登录凭证。我们可以使用wx.login()方法并得到一个登录凭证。

我们可以在小程序的App代码中发起登录凭证请求,也可以在其他任何Page页面代码中发起登录凭证请求,主要根据你小程序的实际需要。

App({
 onLaunch: function() {
 wx.login({
  success: function(res) {
  var code = res.code;
  if (code) {
   console.log('获取用户登录凭证:' + code);
  } else {
   console.log('获取用户登录态失败:' + res.errMsg);
  }
  }
 });
 }
})

步骤2:将登录凭证发往你的服务端,并在你的服务端使用该凭证向微信服务器换取该微信用户的唯一标识(openid)和会话密钥(session_key)

首先,我们使用wx.request()方法,请求我们自己实现的一个后台API,并将登录凭证(code)携带过去,例如在我们前面代码的基础上增加:

App({
 onLaunch: function() {
 wx.login({
  success: function(res) {
  var code = res.code;
  if (code) {
   console.log('获取用户登录凭证:' + code);

   // --------- 发送凭证 ------------------
   wx.request({
   url: 'https://www.my-domain.com/wx/onlogin',
   data: { code: code }
   })
   // ------------------------------------

  } else {
   console.log('获取用户登录态失败:' + res.errMsg);
  }
  }
 });
 }
})

你的后台服务(/wx/onlogin)接着需要使用这个传递过来的登录凭证,去调用微信接口换取openid和session_key,接口地址格式如下所示:

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

这里是我使用了Node.js Express构建的后台服务的代码,仅供参考:

router.get('/wx/onlogin', function (req, res, next) {
 let code = req.query.code

 request.get({
 uri: 'https://api.weixin.qq.com/sns/jscode2session',
 json: true,
 qs: {
  grant_type: 'authorization_code',
  appid: '你小程序的APPID',
  secret: '你小程序的SECRET',
  js_code: code
 }
 }, (err, response, data) => {
 if (response.statusCode === 200) {
  console.log("[openid]", data.openid)
  console.log("[session_key]", data.session_key)

  //TODO: 生成一个唯一字符串sessionid作为键,将openid和session_key作为值,存入redis,超时时间设置为2小时
  //伪代码: redisStore.set(sessionid, openid + session_key, 7200)

  res.json({ sessionid: sessionid })
 } else {
  console.log("[error]", err)
  res.json(err)
 }
 })
})

这段后台代码成功执行的话,就可以得到openid和session_key。这个信息就是当前微信账户在微信服务器那边的登录态了。

但是,为了安全方面的原因,请不要直接使用这些信息作为你小程序的用户标识和session标识回传到小程序客户端中去,我们应该在服务器端做一层自己的session,将这个微信账号登录态生成一个session id并维护在我们自己的session机制中,然后把这个session id派发到小程序客户端作为session标识来使用。

关于如何在服务器端做这个session机制,我们现在一般采用键值对存储工具来做,比如redis。我们为每个session生成一个唯一的字符串作为键,然后可以将session_key和openid作为值,存入redis中,为了安全,存入的时候还应设置一个超时的时间。

步骤3:在客户端保存sessionid

开发Web应用的时候,在客户端(浏览器)中,我们通常将session id存放在cookie中,但是小程序没有cookie机制,所以不能采用cookie了,但是小程序有本地的storage,所以我们可以使用storage来保存sessionid,以供后续的后台API调用所使用。

在之后,调用那些需要登录后才有权限的访问的后台服务时,你可以将保存在storage中的sessionid取出并携带在请求中(可以放在header中携带,也可以放在querystring中,或是放在body中,根据你自己的需要来使用),传递到后台服务,后台代码中获取到该sessionid后,从redis中查找是否有该sessionid存在,存在的话,即确认该session是有效的,继续后续的代码执行,否则进行错误处理。

这是一个需要session验证的后台服务示例,我的sessionid是放在header中传递的,所以在这个示例中,是从请求的header中获取sessionid:

router.get('/wx/products/list', function (req, res, next) {
 let sessionid = req.header("sessionid")
 let sessionVal = redisStore.get(sessionid)

 if (sessionVal) {
 // 执行其他业务代码
 } else {
 // 执行错误处理
 }
})

好了,通过微信账号进行小程序登录和状态维护的简单流程就是这样,了解这些知识点之后,再基于此进行后续的开发就会变得更容易了。

另外,腾讯前端团队也开源了他们封装的相关库,可以借鉴和使用。

服务器端库 weapp-session

小程序端库 weapp-session-client

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript 文件的同步加载与异步加载实现原理
Dec 13 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
Jan 15 Javascript
浅析javascript中的事件代理
Nov 06 Javascript
js实现拖拽效果(构造函数)
Dec 14 Javascript
JavaScript数据绑定实现一个简单的 MVVM 库
Apr 08 Javascript
JavaScript交换两个变量值的七种解决方案
Dec 01 Javascript
利用Vue.js+Node.js+MongoDB实现一个博客系统(附源码)
Apr 24 Javascript
JavaScript之Map和Set_动力节点Java学院整理
Jun 29 Javascript
Vue基本使用之对象提供的属性功能
Apr 30 Javascript
JS多个异步请求 按顺序执行next实现解析
Sep 16 Javascript
通过原生vue添加滚动加载更多功能
Nov 21 Javascript
es6中new.target的作用和使用场景简单示例分析
Mar 14 Javascript
Angular获取手机验证码实现移动端登录注册功能
May 17 #Javascript
原生JS实现层叠轮播图
May 17 #Javascript
JavaScript手风琴页面制作
May 17 #Javascript
jQuery查找dom的几种方法效率详解
May 17 #jQuery
bootstrap的工具提示实例代码
May 17 #Javascript
js字符串与Unicode编码互相转换
May 17 #Javascript
JavaScript实现省市县三级级联特效
May 16 #Javascript
You might like
IIS环境下快速安装、配置和调试PHP5.2.0
2006/12/17 PHP
php中常见的sql攻击正则表达式汇总
2014/11/06 PHP
PHP可变变量学习小结
2015/11/29 PHP
在b/s开发中经常用到的javaScript技术
2006/08/23 Javascript
javascript控制frame,iframe的src属性代码
2009/12/31 Javascript
javascript对象之内置对象Math使用方法
2010/04/16 Javascript
javascript 伪数组实现方法
2010/10/11 Javascript
JavaScript中数组对象的那些自带方法介绍
2013/03/12 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
关于JavaScript对象的动态选择及遍历对象
2014/03/10 Javascript
JavaScript的类型、值和变量小结
2015/07/09 Javascript
JQuery zClip插件实现复制页面内容到剪贴板
2015/11/02 Javascript
JS延时器提示框的应用实例代码解析
2016/04/27 Javascript
jQuery 3.0十大新特性最终版发布
2016/07/14 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
2016/12/07 Javascript
jQuery DateTimePicker 日期和时间插件示例
2017/01/22 Javascript
js canvas实现放大镜查看图片功能
2017/06/08 Javascript
vue使用element-ui的el-input监听不了回车事件的解决方法
2018/01/12 Javascript
JavaScript中var、let、const区别浅析
2018/06/24 Javascript
小程序getLocation需要在app.json中声明permission字段
2019/04/04 Javascript
vue自动路由-单页面项目(非build时构建)
2019/04/30 Javascript
vue实现前台列表数据过滤搜索、分页效果
2019/05/28 Javascript
element跨分页操作选择详解
2020/06/29 Javascript
python使用scrapy解析js示例
2014/01/23 Python
python求众数问题实例
2014/09/26 Python
python实现的多线程端口扫描功能示例
2017/01/21 Python
Python3结合Dlib实现人脸识别和剪切
2018/01/24 Python
python保存文件方法小结
2018/07/27 Python
Python的iOS自动化打包实例代码
2018/11/22 Python
Python实现的微信红包提醒功能示例
2019/08/22 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
CSS3 3D制作实战案例分析
2016/09/18 HTML / CSS
酒店前厅员工辞职信
2014/01/08 职场文书
小学生班会演讲稿
2014/01/09 职场文书
40岁生日感言
2014/02/15 职场文书
房屋所有权证明
2015/06/19 职场文书