关于微信小程序登录的那些事


Posted in Javascript onJanuary 08, 2019

前言

最近团队在开发一款小程序,都是新手,一边看文档,一边开发。在开发中会遇到各种问题,今天把小程序登录这块的流程整理下,做个记录。

小程序的登录跟平时自己APP这种登录验证还不太一样,多了一个角色,那就是微信服务器。

关于微信小程序登录的那些事

根据微信官方提供的登录流程时序图可以清楚的了解小程序登录需要多少个步骤,下面我们来总结下:

  • 小程序启动,通过wx.login()获取code
  • 开发者服务器需要提供一个登录的接口,参数就是小程序获取的code
  • 登录接口收到code后,调用微信提供的接口进行code的验证
  • 得到验证结果,成功后能得到一个session_key和openid
  • 生成一个自定义的key, 将session_key和openid跟自定义的key关联起来
  • 将自定义的key返回给小程序
  • 每次请求都带上key, 后端根据key获取openid识别当前用户身份

首先code是微信给的,如果你随意生成code去验证肯定是无效的,只有微信给的code才有效。code传到开发者自己的服务后,再去问微信:

Hi 哥们,我这个code是有效的还是无效的啊?

微信会告诉你是有效还是无效,有效的情况下还会给你一个用户的标识,也就是openid,同时还会有一个sessionkey,也就是会话的key。sessionkey的有效期默认是2小时,当用户一直在使用小程序的话会自动刷新,这个是由微信这边来维护的。

注意:

  • 会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
  • 临时登录凭证 code 只能使用一次

所以我们要为session_key创建别名,这个别名关联的哪个用户只有我们自己知道,唯一需要做的工作就在这块。

我推荐2种方式来做关联:

第一种:随机生成key, 关联openid,存入redis中,当请求带入key,直接从redis中获取openid得到当前用户信息,这个其实也就是我们自己去维护了会话信息

第二种:采用JWT生成token,将openid绑定到token中,将token返回给小程序,请求的时候带上token,通过解析token得到用户信息。

下面我们以第二种方式来进行讲解,会贴上部分代码:

小程序中在app.js中的onLaunch方法中增加获取code方法,并且调用后端的登录接口获取token:

wx.login({
 success: function (res) {
 var code = res.code;
 if (code) {
  console.log('app启动获取用户登录凭证:' + code);
  let params = { "code": code };
  let result = config.requestHttp(config.url.userLogin, 'POST', params)
  result.then(res => {
  let data = res.data
  if (data.code == 200) {
  wx.setStorageSync("login_token", data.data.token);
  }
  }).catch(err => {
  console.log(err)
  });
 } else {
  console.log('获取用户登录态失败:' + res.errMsg);
 }
 }
})

userLogin接口则根据小程序的code去调用微信接口验证:

// 小程序获取SessionKey接口地址
String loginUrl = "https://api.weixin.qq.com/sns/jscode2session";
String url = loginUrl + "?appid=%s&secret=%s&grant_type=%s&js_code=%s";
url = String.format(url, appid, appSecret, grantType, param.getCode());
String result = restTemplate.getForObject(url, String.class);
Map<String, Object> map = JsonUtils.toBean(Map.class, result);

// 请求成功
if (map.containsKey("session_key")) {
 String openid = map.get("openid").toString();
 // 第一次保存到用户表,生成JWT TOKEN返回
}

小程序端需要将 wx.request()封装成一个通用的方法,所有跟后台交互都用这个方法来调用接口,我们可以在这个方法中设置登录之后获取的Token。这样每次请求都会将Token塞到请求头中,我们在网关中就可以获取这个Token进行解析验证。

//请求封装
function requestHttp(url, method, data) {
 //请求头设置
 var header = {
 Authorization: wx.getStorageSync("login_token")
 }

 return new Promise((resolve, reject) => {
 wx.request({
  url: config.home_config + url,
  data: data,
  header: header,
  method: method,
  success: (res => {
  if (res.data.code === 200) {
   resolve(res)
  } else {
   reject(res)
  }
  }),

  fail: (res => {
  reject(res)
  })
 })
 })
}

Zuul中进行验证:

RequestContext ctx = RequestContext.getCurrentContext();
 HttpServletRequest request = ctx.getRequest();
 String token = request.getHeader("Authorization");

 if (StringUtils.isBlank(token)) {
   ctx.setSendZuulResponse(false);
   ctx.set("isSuccess", false);
   ctx.setResponseBody(JsonUtils.toJson(Response.fail("非法请求【缺少Authorization】", ResponseCode.NO_AUTH_CODE)));
   ctx.getResponse().setContentType("application/json; charset=utf-8");
   return null;
 }

 // 验证Token是否有效
 JWTResult jwResult = JWTUtils.checkToken(token);
 if (!jwResult.isStatus()) {
   ctx.setSendZuulResponse(false);
   ctx.set("isSuccess", false);
   ctx.setResponseBody(JsonUtils.toJson(Response.fail(jwResult.getMsg(), jwResult.getCode())));
   ctx.getResponse().setContentType("application/json; charset=utf-8");
   return null;
 }

 ctx.addZuulRequestHeader("loginUserId", jwResult.getUid());
 return null;

验证成功后将用户ID设置到请求头中,传递给后端服务使用。

使用JWT必然有一个问题是Token的失效问题,我这边失效时间设置的为2个小时,正常的话用户打开小程序,使用不可能连续超过2个小时,登录的逻辑是在app.js中做的,只要下次进去token就会重新申请。不过这个也可以调整,比如稍微长一点。

核心就是用户的认证交给了微信,只要微信告诉我们认证成功了,我们就可以自己接管会话信息了。

总结

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

Javascript 相关文章推荐
JavaScript中各种编码解码函数的区别和注意事项
Aug 19 Javascript
几种设置表单元素中文本输入框不可编辑的方法总结
Nov 25 Javascript
跨域传值即主页面与iframe之间互相传值
Dec 09 Javascript
jQuery模拟点击A标记示例参考
Apr 17 Javascript
js实现Select下拉框具有输入功能的方法
Feb 06 Javascript
JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)
Oct 10 Javascript
Vue组件实例间的直接访问实现代码
Aug 20 Javascript
Bootstrap Table 删除和批量删除
Sep 22 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
Nov 27 jQuery
详解从vue-loader源码分析CSS Scoped的实现
Sep 23 Javascript
原生JS实现拖拽效果
Dec 04 Javascript
React四级菜单的实现
Apr 08 Javascript
Vue2.x Todo之自定义指令实现自动聚焦的方法
Jan 08 #Javascript
关于React动态加载路由处理的相关问题
Jan 07 #Javascript
vue+iview 兼容IE11浏览器的实现方法
Jan 07 #Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
Jan 07 #Javascript
利用React Router4实现的服务端直出渲染(SSR)
Jan 07 #Javascript
Node.js EventEmmitter事件监听器用法实例分析
Jan 07 #Javascript
小程序二次贝塞尔曲线实现购物车商品曲线飞入效果
Jan 07 #Javascript
You might like
php页面,mysql数据库转utf-8乱码,utf-8编码问题总结
2015/08/27 PHP
php导出生成word的方法
2015/12/25 PHP
php实现简易计算器
2020/08/28 PHP
在iframe里的页面编写js,实现在父窗口上创建动画效果展开和收缩的div(不变动iframe父窗口代码)
2011/12/20 Javascript
JavaScript window.document的属性、方法和事件小结
2012/10/24 Javascript
JS实现的省份级联实例代码
2013/06/24 Javascript
JS获取子窗口中返回的数据实现方法
2016/05/28 Javascript
JavaScript基于对象去除数组重复项的方法
2016/10/09 Javascript
关于微信jssdk实现多图片上传的一点心得分享
2016/12/13 Javascript
js遍历json对象所有key及根据动态key获取值的方法(必看)
2017/03/09 Javascript
vue页面切换到滚动页面显示顶部的实例
2018/03/13 Javascript
对Vue beforeRouteEnter 的next执行时机详解
2018/08/25 Javascript
elementUI select组件使用及注意事项详解
2019/05/29 Javascript
vue实现购物车的监听
2020/04/20 Javascript
vue实践---vue不依赖外部资源实现简单多语操作
2020/09/21 Javascript
vue打包通过image-webpack-loader插件对图片压缩优化操作
2020/11/12 Javascript
[43:32]Winstrike vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
[36:33]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.29
2020/12/02 DOTA
使用python提取html文件中的特定数据的实现代码
2013/03/24 Python
基于python的多进程共享变量正确打开方式
2018/04/28 Python
python指定写入文件时的编码格式方法
2018/06/07 Python
详谈Pandas中iloc和loc以及ix的区别
2018/06/08 Python
python 函数内部修改外部变量的方法
2018/12/18 Python
Django之PopUp的具体实现方法
2019/08/31 Python
Python笔记之工厂模式
2019/11/20 Python
python实现超级玛丽游戏
2020/03/18 Python
香港钟表珠宝首饰商城:OneMallTime网摩间
2016/10/14 全球购物
美体小铺加拿大官方网站:The Body Shop加拿大
2016/10/30 全球购物
法学专业应届生求职信
2013/10/16 职场文书
告诉你怎样写创业计划书
2014/01/27 职场文书
运动会邀请函范文
2014/01/31 职场文书
《画》教学反思
2014/04/14 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
社区党支部承诺书
2015/04/29 职场文书
Netty分布式客户端处理接入事件handle源码解析
2022/03/25 Java/Android
win10截图快捷键win+shift+s没有反应无法截图怎么解决?
2022/08/14 数码科技