从零开始搭建物联网平台(10):微信登录和用户绑定

微信小程序不支持Cookie的,所以为了保存用户登录状态就必须换一个方式实现,这里采用jwt的方式,关于jwt简单来说就是第一次登录验证成功后对想要保存的信息进行加密,然后将加密过后的内容返回给前端,前端每次请求的时候都携带上这个token,后端拿到token后对其解密就能获取之前保存的信息了。

整体流程:

这里先看一下小程序官方给的登录流程,这只是最基础的流程,根据设计需要我们还需要添加自己的逻辑进去

下面是具体的流程图,接下来会根据这个流程图具体看看小程序端和后端应该怎么实现。
从零开始搭建物联网平台(10):微信登录和用户绑定_第1张图片

小程序的具体实现

以index页面为起始页面,当页面进行加载的时候会调用onload函数,所以可以在onload函数中检测storage中是否有jwt

onLoad: function() { 
    // 获取本地的jwt,如果有则跳转到home页面,否则重新获取jwt
    wx.getStorage({
      key: 'jwt',
      success: function(res) {
        wx.switchTab({
          url: '../home/home'
        })
      },
    })
  },

如果没有找到jwt,这是会调用登录函数从后端获取jwt

//用户登录
let login = function(code) {
  wx.request({
    url: login_url,
    method: 'post',
    data: {
      'code': code
    },
    success(res) {
      // 登录成功
      if (res.data.code === 0) {
        // 将后台返回的jwt写入storage中保存
        // 这里要使用同步的方法,避免异步请求的时候没有token
        wx.setStorageSync('jwt', res.data.data)
        // 跳回主页
        wx.switchTab({
          url: '../home/home'
        })
      }
      // 登录失败没有找到绑定的信息,跳转到绑定页面
      else {
        wx.navigateTo({
          url: '../bind/bind',
        })
      }
    },
    fail(res) {
      wx.showToast({
        title: '服务器错误,登录失败!',
        duration: 1000,
        icon: 'none',
      })
    }
  })
}

在bind页面中,需要填写我们的账户信息,这里使用了小程序的form、input组件,需要对password进行MD5加密处理后再提交输入的内容,后端会验证用户名和密码,如果成功后会将获取到的openID和这个用户绑定,并生成jwt。

//用户绑定
let bind = function(username, password) {
  var password = md5(password)
  //重新获取code避免长时间code失效
  wx.login({
    success: res => {
      wx.request({
        url: bind_url,
        method: 'POST',
        data: {
          'username': username,
          'password': password,
          'code': res.code
        },
        success(res) {
          // 绑定成功
          if (res.data.code === 0) {
            // 将后台返回的jwt写入storage中保存
            // 这里要使用同步的方法,避免异步请求的时候没有token
            wx.setStorageSync('jwt', res.data.data)
            // 跳回主页
            wx.switchTab({
              url: '../home/home'
            })
          } else {
            wx.showToast({
              title: res.data.msg,
              duration: 1000,
              icon: 'none',
            })
          }
        },
        fail(res) {
          wx.showToast({
            title: '服务器错误,绑定失败!',
            duration: 1000,
            icon: 'none',
          })
        }
      })
    }
  })
}

注册页面和绑定页面逻辑基本类似就不在此多说了

后端的具体实现

这里使用了PyJWT去生成jwt和解码jwt
openid的获取,下面官方对请求参数的要求
从零开始搭建物联网平台(10):微信登录和用户绑定_第2张图片

def get_openid(code):
    """
    获取微信的openID
    :param code:
    :return: openid 
    """
    # 构建请求参数
    payload = {'appid': settings.WX_APPID,
               'secret': settings.WX_SECRET,
               'js_code': code,
               'grant_type': 'authorization_code'}
    # 请求微信接口,获取用户的openID
    recv = requests.get("https://api.weixin.qq.com/sns/jscode2session", params=payload)
    if recv.status_code == 200:
        recv = json.loads(recv.text)
        return recv['openid']
    else:
        return ''

用户登录接口

    def post(request):
        """
        微信端登录
        :param request: data{ code }
        :return: {'code': 0, 'msg': '', 'data': jwt}
        """
        res = {'code': 0, 'msg': '', 'data': ''}
        try:
            code = request.data.get('code')
            if code:
                openid = get_openid(code)
                # 通过openID查找用户信息
                user_obj = UserInfo.objects.filter(wx=openid).first()
                # 找到用户后生成
                if user_obj:
                    # 生成jwt并返回
                    res['data'] = create_jwt.create_jwt(user_id=user_obj.uid)
                # 没有查找到对应用户提示先进行绑定
                else:
                    res['code'] = 1001
                    res['msg'] = '请先绑定微信'
            else:
                res['code'] = 1002
                res['msg'] = '登录失败'
        except Exception :
            res['code'] = 1003
            res['msg'] = '登录失败'
        return JsonResponse(res)

用户绑定接口:

    def post(request):
        """
        绑定微信
        :param request: data{username, password, code}
        :return: {'code': 0, 'msg': '', 'data': jwt}
        """
        res = {'code': 0, 'msg': '', 'data': ''}
        try:
            print(request.data)
            code = request.data.get('code')
            openid = get_openid(code)
            # 获取openID
            data = request.data.copy()
            data['openid'] = openid
            # 表单验证
            login_form = LoginForm(data)
            # 验证失败
            if not login_form.is_valid():
                res['code'] = 1
                for i, error in login_form.errors.items():
                    res['msg'] = error[0]
            # 验证成功,生成jwt并返回给客户端
            else:
                res['data'] = create_jwt.create_jwt(user_id = login_form.cleaned_data.get('uid'))
        except Exception:
            res['code'] = 1
            res['msg'] = '绑定失败'
        return JsonResponse(res)

至此这个微信小程序的登录和绑定基本完成了,下面是绑定、注册页面效果图

从零开始搭建物联网平台(10):微信登录和用户绑定_第3张图片从零开始搭建物联网平台(10):微信登录和用户绑定_第4张图片

你可能感兴趣的:(物联网)