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


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 相关文章推荐
动态添加js事件实现代码
Mar 12 Javascript
js控制的遮罩层实例介绍
May 29 Javascript
js购物车实现思路及代码(个人感觉不错)
Dec 23 Javascript
jQuery取得iframe中元素的常用方法详解
Jan 14 Javascript
Javascript blur与click冲突解决办法
Jan 09 Javascript
详解Node.js开发中的express-session
May 19 Javascript
EasyUI的DataGrid每行数据添加操作按钮的实现代码
Aug 22 Javascript
Node.js如何使用Diffie-Hellman密钥交换算法详解
Sep 05 Javascript
加载 vue 远程代码的组件实例详解
Nov 20 Javascript
使用layui监听器监听select下拉框,事件绑定不成功的解决方法
Sep 28 Javascript
angularjs模态框的使用代码实例
Dec 20 Javascript
Vue+abp微信扫码登录的实现代码示例
Jan 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实现伪静态方法汇总
2016/01/13 PHP
在laravel中实现ORM模型使用第二个数据库设置
2019/10/24 PHP
javascript 树控件 比较好用
2009/06/11 Javascript
向大师们学习Javascript(视频与PPT)
2009/12/27 Javascript
javascript采用数组实现tab菜单切换效果
2012/12/12 Javascript
JavaScript的arguments对象应用示例
2014/09/15 Javascript
node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法
2014/11/20 Javascript
JavaScript中window.showModalDialog()用法详解
2014/12/18 Javascript
JS实现动态移动层及拖动浮层关闭的方法
2015/04/30 Javascript
bootstrap中添加额外的图标实例代码
2017/02/15 Javascript
Vue2学习笔记之请求数据交互vue-resource
2017/02/23 Javascript
JavaScript编写一个贪吃蛇游戏
2017/03/09 Javascript
jquery select插件异步实时搜索实例代码
2017/10/20 jQuery
Node.js使用Koa搭建 基础项目
2018/01/08 Javascript
小程序scroll-view组件实现滚动的示例代码
2018/09/20 Javascript
详解ES6 Fetch API HTTP请求实用指南
2018/11/14 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
基于vue 动态菜单 刷新空白问题的解决
2020/08/06 Javascript
vue3.0中使用element的完整步骤
2021/03/04 Vue.js
[43:24]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第二场 12.12
2020/12/17 DOTA
python对html代码进行escape编码的方法
2015/05/04 Python
用Python分析3天破10亿的《我不是药神》到底神在哪?
2018/07/12 Python
Python Unittest根据不同测试环境跳过用例的方法
2018/12/16 Python
python实现美团订单推送到测试环境,提供便利操作示例
2019/08/09 Python
Python3 字典dictionary入门基础附实例
2020/02/10 Python
tensorflow 分类损失函数使用小记
2020/02/18 Python
call在Python中改进数列的实例讲解
2020/12/09 Python
选购国际女性时装设计师品牌:IFCHIC(支持中文)
2018/04/12 全球购物
实习自我鉴定
2013/12/15 职场文书
幼儿园毕业典礼主持词
2014/03/21 职场文书
公司员工体检通知
2015/04/21 职场文书
隐形的翅膀观后感
2015/06/10 职场文书
2015年暑期社会实践报告
2015/07/13 职场文书
煤矿安全学习心得体会
2016/01/18 职场文书
关于antd tree 和父子组件之间的传值问题(react 总结)
2021/06/02 Javascript
Python函数中apply、map、applymap的区别
2021/11/27 Python