客户端

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

 <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
}

版权声明:本文为samwu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/samwu/p/12596010.html