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


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 相关文章推荐
Windows Live的@live.com域名注册漏洞 利用代码
Dec 27 Javascript
JS中不为人知的五种声明Number的方式简要概述
Feb 22 Javascript
HTML5+setCutomValidity()函数验证表单实例分享
Apr 24 Javascript
简介JavaScript中用于处理正切的Math.tan()方法
Jun 15 Javascript
详解JavaScript中的Unescape()和String() 函数
Nov 09 Javascript
JavaScript代码里的判断小结
Aug 22 Javascript
Javascript计算二维数组重复值示例代码
Dec 18 Javascript
Vue数据驱动模拟实现5
Jan 13 Javascript
jQuery animate()实现背景色渐变效果的处理方法【使用jQuery.color.js插件】
Mar 15 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
May 16 Javascript
jQuery实现鼠标滑动切换图片
May 27 jQuery
nuxt.js服务端渲染中axios和proxy代理的配置操作
Nov 06 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
PHP写入WRITE编码为UTF8的文件的实现代码
2008/07/07 PHP
PHP教程 基本语法
2009/10/23 PHP
PHP使用DES进行加密与解密的方法详解
2013/06/06 PHP
php 不使用js实现页面跳转
2014/02/11 PHP
php单文件版在线代码编辑器
2015/03/12 PHP
PHP函数rtrim()使用中的怪异现象分析
2017/02/24 PHP
js中的值类型和引用类型小结 文字说明与实例
2010/12/12 Javascript
js的alert弹出框出现乱码解决方案
2013/09/02 Javascript
jQuery使用andSelf()来包含之前的选择集
2014/05/19 Javascript
Js可拖拽放大的层拖动特效实现方法
2015/02/25 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
教你用javascript实现随机标签云效果_附代码
2016/03/16 Javascript
js实现的下拉框二级联动效果
2016/04/30 Javascript
js仿手机页面文件下拉刷新效果
2016/10/14 Javascript
微信小程序页面传值实例分析
2017/04/19 Javascript
详解AngularJS 模块化
2017/06/14 Javascript
React路由管理之React Router总结
2018/05/10 Javascript
jQuery实现获取动态添加的标签对象示例
2018/06/28 jQuery
微信小程序缓存过期时间的使用详情
2019/05/12 Javascript
微信小程序跳转到其他网页(外部链接)的实现方法
2019/09/20 Javascript
探索node之事件循环的实现
2020/10/30 Javascript
vue项目实现减少app.js和vender.js的体积操作
2020/11/12 Javascript
JS实现页面侧边栏效果探究
2021/01/08 Javascript
一个检测OpenSSL心脏出血漏洞的Python脚本分享
2014/04/10 Python
利用Hyperic调用Python实现进程守护
2018/01/02 Python
简单了解django缓存方式及配置
2019/07/19 Python
在Python中使用filter去除列表中值为假及空字符串的例子
2019/11/18 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
Jupyter Notebook的连接密码 token查询方式
2020/04/21 Python
有关HTML5中背景音乐的自动播放功能
2017/10/16 HTML / CSS
万得城电器土耳其网站:欧洲第一大电子产品零售商
2016/10/07 全球购物
生产车间主任的个人自我鉴定
2013/10/25 职场文书
行政部总经理岗位职责
2014/01/04 职场文书
法定代表人身份证明书(含说明)
2014/10/02 职场文书
大学生就业协议书范本(适用于公司企业)
2014/10/07 职场文书
消防演习通知
2015/04/25 职场文书