前言
上一篇的的的链接 赖了一个星期了, let us 接着上一篇的搞.
在上一篇里搞了一下基础设施建设, 这一篇我们... 稍微搞那么一丢丢上层建筑.
这一篇里本菜鸡想分享的 tip
小程序登陆逻辑与登陆状态维持的两种姿势
发送评论时的一个投机倒把的小 "优化"
小程序微信登陆与前端登陆状态保存
小程序登陆
小程序登陆其实是个比较简单的基本操作, 但凡是看过微信开发文档的应该都能懂, 不过本菜鸡还是想尝试性的分享一下.
首先先明确一下为啥要用微信登陆, 在本菜鸡看来在这个项目里使用微信登陆主要有三个目的
方便用户 : 相比于用户手动注册, 填写各种信息, 再手动输入账号密码登陆, 利用微信登陆用户点一下, 就可以完成上面的全部操作, 注册, 登陆全都由后台利用微信提供的相关的信息完成
方便后台用户管理
使用微信的相关能力: 通过微信登陆, 后台可以获得唯一标识用户的 openid, 而这个 openid, 是后台调用微信相关敏感接口的必填项 (例如: 微信支付)
然后, 明确一下微信登陆过程中的几个概念
名称 | 获取方式 | 特点 | 用法 |
---|---|---|---|
code | 通过小程序端调用 wx.login 方法 | 一次性的,每次调用 wx.login 所得到的 code 均不同 | 传递给后台,与 appid、appsecrect 拼接成微信登陆的 url |
openid | 通过访问微信登陆 url(由 appid、appsecrect、code 拼接而成)得到的返回结果 json 中取到 | 1. 能唯一的标识出本小程序的用户 2. 属于敏感信息应存放在后台 3. 后台调用微信一些高级接口的必填项 | |
appid | 微信公众平台后台 | 每个小程序的唯一标识 属于敏感信息应存放在后台 | 后台调用微信接口的必须项 |
appsecrect | 微信公众平台后台 | 属于敏感信息应存放在后台 | 后台调用敏感微信接口的必须项 |
然后, 结合本次项目的实际情况捋一下微信登陆的流程
调用 wx.login 方法获取 code, 顺手调用一下 wx.getUserInfo 获取一下用户的基本信息 (头像, 微信名啥的)
调用后端接口, 将 code 与获取的用户信息 userInfo(非必需) 传递给后端.
后端接收到参数, 将 code 拿出来与存在后端的 appid,appsecrect 拼接成微信登陆链接
$url='https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appId.'&secret='.$this->appSecret.'&js_code='.$code.'&grant_type=authorization_code';
访问该链接获得返回结果 (JSON 格式的), 验证下是否成功, 如果 OJBK, 就从结果里掏出 openid
- $wxResult=json_decode(curl_get($url),true);
- if(!$wxResult||!array_key_exists('openid',$wxResult)){
- return ResultService::failure('获取 openid 不成功');
- }
- $openId=$wxResult['openid'];
其实获得到 openid 微信登陆已经差不多了, 剩下就是怎么用的问题了, 下面的步骤是在本次项目的流程, 供各位老哥参考
根据 openid 查一下数据库, 看看是否是存在, 若存在, 则说明是老用户, 不用新增用户, 直接用在步骤 3 中获取到的由前端传来的 userInfo 更新一下后台的用户信息即可 (头像, 省份, 微信名啥的). 若不存在, 则这是个新用户, 把 openid 与 userInfo 存到用户表中
经过步骤 5, 库里已经有了这个用户的数据, 然后拿用户数据, 按照一定规则, 生成个 token 返回给小程序端, 小程序端把 token 存到 localStorage 里, 后端将 token 与用户信息以键值对的形式存到缓存里, 以后小程序请求的时候带着 token 来, 后端根据 token 查缓存来确定用户登陆状态.
至此, 本项目中微信登陆的流程搞完了. 登陆完的结果就是, 后台新增或更新了用户数据, 小程序端有了 token.
小程序登陆状态保持
本菜鸡个人觉得常用的保持登陆状态的方法有两种
- token(个人推荐)
- session
先说第一种, 也是本项目采用的方法, 其实在上面的步骤 5,6 已经把这个方法将清楚了,
登陆后服务端下发 token 给小程序端,
同时服务端自己也存一份, 存哪里就根据实际情况 (cache,Redis,session 啥的都行), 然后搞个有效期, 过期了就消失得那种.
小程序每次请求后端接口的时候把 token 放到 header 里
后端在处理请求前先把 token 从 header 里取出来, 拿这个 token 去查缓存, 如果有, 就说明用户还在登陆状态, 继续往后走, 如果没有, 则说明用户离线了, 就直接返回一下告诉小程序端需要重新登陆, 小程序收到后跳转到登录页.
第二种也在做网站用户登陆的时候是非常常见的操作, 在撸网站的时候, 用户登陆后把用户信息存到 session 里, 用户在请求的时候能够从 session 中取到用户信息, 之所以这样是因为, 浏览器请求服务器, 服务器响应时, 会带一个 sessionid 回去给浏览器, 浏览器下次请求时候会自动带着 sessionid, 服务器会根据 sessionid 来到相应的会话里, 所以能取到 session 中的用户
BUT 在小程序中有所不同, 这是因为小程序网络访问是用的微信封装的 wx.request, 而该方法并不会把 sessionid 存下来, 因此, 为了能和网站登陆搞成一个逻辑, 我们手动存一下 sessionid, 在下次请求的时候带着 sessionid 去即可.
部分代码如下
服务端 (PHP)
- // 前面先搞登陆, 登陆完了把用户存到 session 里然后
- return ResultService::success('',['sessionId'=>session_id()]);
小程序端
- // 登陆
- dataUtils.userLogin({ code: code, info: JSON.stringify(info) }).then(res => {
- if (res.statusCode == '200') {
- wx.setStorageSync('sessionId', res.data.data.sessionId);
- $Message({
- content: '登陆成功',
- type: 'success'
- });
- this.checkUserLogin();
- }
- else {
- $Message({
- content: '登陆未成功',
- type: 'error'
- });
- }
- // 请求例子 (不同后端 header 名不一样, 比如 PHP 的后端就是 PHPSESSID = 你的 sessionId)
- function userJoinPromise(data,sessionId){
- let url = 'travel/api/userJoin';
- return getServerDataPromise(url, data, { 'Cookie': 'PHPSESSID=' + sessionId });
- }
下班了下班了, 先写到这明天继续撸
来源: https://juejin.im/post/5bea72ae5188254b0917f5d2