django与小程序实现登录验证功能的示例代码


Posted in Python onFebruary 19, 2019

之前用小程序做项目,因为后台使用的java开发,一切顺利,但切换成django做RESTful API接口时,在登陆注册时一直出现问题,网上搜索,借助一个网友的回答,找到了一种可行的解决方案,现记录如下。

具体流程

  • 用户点击小程序页面上的登录授权认证
  • 通过微信自带的认证获取code
  • 调取登录接口,将code传入后台
  • 后台拿到code调用微信接口获取openid等用户信息
  • 后台将openid作为用户名,若存在则去校验用户信息,否则以此用户名创建新用户,密码随机生成
  • 将校验结果或者创建信息返回给微信小程序端
  • 根据返回的信息完成用户登录校验

django的用户权限认证

django有一套自己的完善用户模型,由于Django Auth自带的User模型字段有限,我们需要对其进行拓展(直接使用也可以)

nickname = models.CharField(verbose_name=u'昵称',max_length=50, blank=True)
user_avatar = models.ImageField(verbose_name=u'用户头像', upload_to='image/%Y/%m/%d', default=u'image/default.png', max_length=500)
user_email = models.EmailField(verbose_name=u'用户邮箱',max_length=254)
user_phone = models.BigIntegerField(verbose_name=u'手机号', null=True,blank=True)
user_birthday = models.DateField(verbose_name=u'出生日期', default = timezone.now)
user_sex = models.CharField(verbose_name=u'性别',max_length=6,choices=(('male','男'),('female','女')),default='male')
user_address = models.CharField(verbose_name=u'地址',max_length=550, blank=True,null=True)
signature = models.CharField(verbose_name=u'个性签名',max_length=550, blank=True,null=True)

用户接口序列化

from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
class Meta:
  model = User
  fields = "__all__"

登陆接口设计

class UserLogin(APIView):
  def post(self,request):
    params = request.data
    userName = get_openid(params.get('code'))
    userInfo = params.get('userinfo')
    try:
      user = User.objects.get(username = userName)
    except Exception as e:
      user = None
    if user:
      # 更新用户信息
      user = User.objects.get(username = userName)
    else:
      #注册新用户
      user = User.objects.create_user(username=userName,password=random_str(10))  
    #手动生成JWT
    # 手动生成token验证
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    payload = jwt_payload_handler(user)
    token = jwt_encode_handler(payload)

    ret = {'code': '00000', 'msg': None,'data':{}}
    
    ret['msg'] = '授权成功'
    ret['data'] = {
      'token': token,
      'user_id': user.id,
      'nickname': user.nickname
    }
    return JsonResponse(ret)

解析code获取openid

class OpenidUtils(object):
  def __init__(self, jscode):
    self.url = "https://api.weixin.qq.com/sns/jscode2session"
    self.appid = APPID
    self.secret = SECRET
    self.jscode = jscode  # 前端传回的动态jscode

  def get_openid(self):
    url = self.url + "?appid=" + self.appid + "&secret=" + self.secret + "&js_code=" + self.jscode + "&grant_type=authorization_code"
    r = requests.get(url)
    openid = r.json()['openid']
    return openid

小程序的登陆验证

具体登录流程可以查阅官方文档。

function getWXUserInfo() {
  const login = promisify(wx.login);
  const getUserInfo = promisify(wx.getUserInfo);

  return new Promise(function (resolve, reject) {
    _wxLogin();
    function _wxLogin() {
      login().then(function (res) {
        getUserInfo().then(function (r) {
          let userInfo = r;
          userInfo.code = res.code;
          try {
            wx.setStorageSync('userInfo', userInfo);
          } catch (e) {
            console.log(e)
          }
          if (userInfo && userInfo.code && userInfo.iv) {
            resolve(userInfo);
          }
          else {
            reject('wx login fail');
          }
        }).catch(function (error) {
          reject(error);
        });
      }).catch(function (error) {
        reject(error);
      });
    }
  });
}

//登录接口验证
getWXUserInfo().then(function (data) {
  var result = {
    code: 0,
    data: {}
  };
  var params = {
    'code':data.code,
    'userinfo':data.userInfo
  }
  wx.request({
    url: '/api/login',
    data: params,
    dataType: 'json',
    method: 'POST',
    success: function (response) {
      // 返回成功
      if (response.data && response.data.code == '00000') {
        try {
          var resData = {
            custNo: data.user_id,
            nickname: data.nickname
          };
          result.code = 0;
          result.data = resData;
          resolve(result);
        }
        catch (e) {
          console.warn(result)
          // 登录失败
          result.code = 2;
          resolve(result);
        }
      }
      else {
        // 获取 customNum 失败
        console.warn(result)
        result.code = 1;
        result.data = 'get customNum fail';
        resolve(result);
      }
    }
  })
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python进行稳定可靠的文件操作详解
Dec 31 Python
python创建线程示例
May 06 Python
python通过wxPython打开一个音频文件并播放的方法
Mar 25 Python
Python实现基于权重的随机数2种方法
Apr 28 Python
Python中使用Queue和Condition进行线程同步的方法
Jan 19 Python
Python实现PS图像调整黑白效果示例
Jan 25 Python
python获取文件路径、文件名、后缀名的实例
Apr 23 Python
使用python list 查找所有匹配元素的位置实例
Jun 11 Python
检测python爬虫时是否代理ip伪装成功的方法
Jul 12 Python
Pandas分组与排序的实现
Jul 23 Python
Python调用JavaScript代码的方法
Oct 27 Python
PyTorch梯度裁剪避免训练loss nan的操作
May 24 Python
实例讲解Python3中abs()函数
Feb 19 #Python
python协程之动态添加任务的方法
Feb 19 #Python
Python同步遍历多个列表的示例
Feb 19 #Python
python读取txt文件并取其某一列数据的示例
Feb 19 #Python
详解Python3注释知识点
Feb 19 #Python
Python3解释器知识点总结
Feb 19 #Python
python 利用文件锁单例执行脚本的方法
Feb 19 #Python
You might like
自己前几天写的无限分类类
2007/02/14 PHP
解析php二分法查找数组是否包含某一元素
2013/05/23 PHP
利用php+mcDropdown实现文件路径可在下拉框选择
2013/08/07 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(九)
2014/06/24 PHP
PHP之密码加密的几种方式
2015/07/29 PHP
php图片添加文字水印实现代码
2016/03/15 PHP
php实现水印文字和缩略图的方法示例
2016/12/29 PHP
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
Javascript实现Web颜色值转换
2015/02/05 Javascript
JavaScript日期类型的一些用法介绍
2015/03/02 Javascript
JS基于VML技术实现的五角星礼花效果代码
2015/10/26 Javascript
jquery插件EasyUI中form表单提交实例分享
2016/01/11 Javascript
nodejs个人博客开发第一步 准备工作
2017/04/12 NodeJs
详解VueRouter进阶之导航钩子和路由元信息
2017/09/13 Javascript
JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
2017/12/01 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
微信小程序动态增加按钮组件
2018/09/14 Javascript
ES6的解构赋值实例详解
2019/05/06 Javascript
JS判断浏览器类型与操作系统的方法分析
2020/04/30 Javascript
解决Vue keep-alive 调用 $destory() 页面不再被缓存的情况
2020/10/30 Javascript
利用打码兔和超人打码自封装的打码类分享
2014/03/16 Python
用Python制作检测Linux运行信息的工具的教程
2015/04/01 Python
Python迭代器与生成器基本用法分析
2018/07/26 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
python中的colorlog库使用详解
2019/07/05 Python
基于Python组装jmx并调用JMeter实现压力测试
2020/11/03 Python
使用canvas来完成线性渐变和径向渐变的功能的方法示例
2019/07/25 HTML / CSS
Original Penguin美国官网:布拉德皮特、强尼德普喜爱的服装品牌
2016/10/25 全球购物
翻新二手苹果产品的网络领导者:Mac of all Trades
2017/12/19 全球购物
北京-环亚运商测试题.net程序员初步测试题
2013/05/28 面试题
网络管理专业求职信
2014/03/15 职场文书
大学开学计划书
2014/04/30 职场文书
巾帼志愿者活动方案
2014/08/17 职场文书
python解决12306登录验证码的实现
2021/04/18 Python
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL
javascript函数式编程基础
2021/09/15 Javascript