• 微信小程序登陆流程(20200322)


    客户端

    开发版和测试版首次登录需要用户手动触发登录。比如点击指定登录组件

     <button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">新版登录</button>
    

    对应的事件处理

    Page({
      bindGetUserInfo: function (e) {
        console.log(e.detail.userInfo)
        if (e.detail.userInfo) {
          // 用户按了接受按钮
          app.doLogin(this.getUserInfo);
        } else {
          //用户按了拒绝按钮
        }
      },
      getUserInfo: function () {
        let that = this;
        let userInfo = app.globalData.userInfo;
        console.info('userInfo is:', userInfo);
    
        if (userInfo) {
          that.setData({
            hasLogin: true,
            userInfo: userInfo
          });
          wx.hideLoading();
        } else {
          console.log('globalData中userInfo为空');
        }
      },
      // 登录动作
      doLogin: function (callback = () => { }) {
        let that = this;
        wx.login({
          success: function (loginRes) {
            log('wx.login执行成功', loginRes);
            if (loginRes.code) {
              /* 
               * @desc: 获取用户信息 期望数据如下 
               *
               * @param: userInfo       [Object]
               * @param: rawData        [String]
               * @param: signature      [String]
               * @param: encryptedData  [String]
               * @param: iv             [String]
               **/
              wx.getUserInfo({
    
                withCredentials: true, // 非必填, 默认为true
    
                success: function (infoRes) {
                  console.log('wx.getUserInfo成功', infoRes)
                  // 请求服务端的登录接口
                  wx.request({
                    url: api.loginUrl,
    
                    data: {
                      code: loginRes.code, // 临时登录凭证
                      rawData: infoRes.rawData, // 用户非敏感信息
                      signature: infoRes.signature, // 签名
                      encryptedData: infoRes.encryptedData, // 用户敏感信息
                      iv: infoRes.iv // 解密算法的向量
                    },
    
                    success: function (res) {
                      console.log('login success');
                      res = res.data;
    
                      if (res.result == 0) {
                        that.globalData.userInfo = res.userInfo;
                        wx.setStorageSync('userInfo', JSON.stringify(res.userInfo));
                        wx.setStorageSync('loginFlag', res.skey);
                        callback();
                      } else {
                        that.showInfo(res.errmsg);
                      }
                    },
    
                    fail: function (error) {
                      // 调用服务端登录接口失败
                      log('调用服务端登录接口失败', error);
                      that.showInfo('调用接口失败');
                      console.log(error);
                    }
                  });
                },
    
                fail: function (error) {
                  // 获取 userInfo 失败,去检查是否未开启权限
                  log('获取 userInfo 失败');
                  wx.hideLoading();
                  that.checkUserInfoPermission();
                }
              });
    
            } else {
              // 获取 code 失败
              that.showInfo('登录失败');
              console.log('调用wx.login获取code失败');
            }
          },
    
          fail: function (error) {
            // 调用 wx.login 接口失败
            that.showInfo('接口调用失败');
            console.log(error);
          }
        });
      },
    })
    

    服务端

    根据客户端传过来的临时登录凭证,以及小程序注册时获取的appidappSecret,可以从微信服务器中拿到登录态标识session_key,进而拿到这个用户的唯一标识openId和其它非敏感信息。
    这个唯一标识openId也可以作为你的业务系统中用户的唯一标识。

    const http = require('axios');
    const crypto = require('crypto');
    const { appConfig: config } = require('../conf/app');
    const { decryptByAES, encryptSha1 } = require('../util/util');
    const { saveUserInfo } = require('../controllers/users');
    /**
     * 登录校验中间件
     */
    function authorizeMiddleware(req, res, next) {
      return authMiddleware(req).then(function (result) {
    
        // 将结果存入响应信息的'auth_data'字段
        res['auth_data'] = result;
        return next();
    
      })
    }
    
    function authMiddleware(req) {
      const {
        appid,
        secret
      } = config;
    
      const {
        code,
        encryptedData,
        iv
      } = req.query;
    
      // 检查参数完整性
      if ([code, encryptedData, iv].some(item => !item)) {
        return {
          result: -1,
          errmsg: '缺少参数字段,请检查后重试'
        }
      }
    
      // 获取 session_key和 openid
      return getSessionKey(code, appid, secret)
        .then(resData => {
          // 选择加密算法生成自己的登录态标识
          const { session_key } = resData;
          const skey = encryptSha1(session_key);
    
          let decryptedData = JSON.parse(decryptByAES(encryptedData, session_key, iv));
          console.log('-------------decryptedData---------------');
          console.log(decryptedData);
          console.log('-------------decryptedData---------------');
    
          // 存入用户数据表中
          return saveUserInfo({
            userInfo: decryptedData,
            session_key,
            skey
          })
        })
        .catch(err => {
          return {
            result: -3,
            errmsg: JSON.stringify(err)
          }
        })
    }
    
    /**
     * 获取当前用户session_key
     * @param {*用户临时登录凭证} code 
     * @param {*小程序appid} appid 
     * @param {*小程序密钥} appSecret 
     */
    function getSessionKey(code, appid, appSecret) {
    
      const opt = {
        method: 'GET',
        url: 'https://api.weixin.qq.com/sns/jscode2session',
        params: {
          appid: appid,
          secret: appSecret,
          js_code: code,
          grant_type: 'authorization_code'
        }
      };
    
      return http(opt).then(function (response) {
        const data = response.data;
    
        if (!data.openid || !data.session_key || data.errcode) {
          return {
            result: -2,
            errmsg: data.errmsg || '返回数据字段不完整'
          }
        } else {
          console.log('jscode2session结果',data);
          return data
        }
    
      });
    }
    module.exports = {
      authorizeMiddleware
    }
    
  • 相关阅读:
    怎样提高js的编程能力
    如何提升自己
    利用nginx做反向代理解决前端跨域问题
    vue项目中使用组件化开发
    vue中refs的使用
    vue项目使用keep-alive的作用
    hadoop安装、使用过程的异常汇总
    CSS选择器优先级总结
    为什么CSS选择器是从右往左解析
    MySql中游标的定义与使用方式
  • 原文地址:https://www.cnblogs.com/samwu/p/12596010.html
Copyright © 2020-2023  润新知