话不多说,直接开始,大概流程如下
1、小程序通过wx.login请求获取用户的code,发送给后端
2、后端通过code换取用户登录凭证,也就是openid
3、后端判断数据库是否存在该用户,不存在,则创建,然后返回token;存在,则直接创建token返回给前端。
微信请求代码块
代码块没有做封装
```
var host = 'http://localhost:8000/user/login'
// 登录
wx.login({
success: res => {
wx.request({
url: host,
method: 'post',
data: res,
success (res) {
if (res.data.status){
wx.setStorageSync('token', res.data.data.token)
}
}
})
console.log(res)
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
```
model
from django.db import models
# Create your models here.
class WeChatUser(models.Model):
#uuid存储用户的openid
uuid = models.CharField(max_length=32, verbose_name='用户唯一识别码',null=True)
username = models.CharField(max_length=32, verbose_name='用户昵称',null=True)
grade = models.CharField(max_length=8,verbose_name='性别',null=True)
city = models.CharField(max_length=32, verbose_name='城市',null=True)
province = models.CharField(max_length=32, verbose_name='省份',null=True)
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
id_delete = models.BooleanField(default=False)
class Meta:
verbose_name = '用户信息表'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
view
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework import viewsets
from .util import info, JwtToken
# Create your views here.
import requests
from .models import WeChatUser
APPID = '填自己的'
SECRET = '填自己的'
class UserAuth(APIView):
def post(self, request):
data = request.data
# 获取前端传过来的code
JSCODE = data.get('code')
if JSCODE:
try:
# 换取微信登录凭证
wx_url = 'https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code'.format(
APPID, SECRET, JSCODE)
wx_res = requests.get(wx_url).json()
except Exception as e:
return info(status=0, message=str(e))
try:
# 查询数据库是否有该用户
ent = WeChatUser.objects.filter(uuid=wx_res['openid']).exists()
# 判断没有该用户则创建该用户
if not ent:
WeChatUser(uuid=wx_res['openid']).save()
# 初始化jwt_token
token_obj = JwtToken()
token = token_obj.encode_token({'uuid': wx_res['openid']})
# 返回给用户
return info(data={'token': token})
except:
return info(status=0, message='服务器内部错误')
return info(status=0, message='未获取到code')
util.py
from uuid import uuid4
import hashlib
import time
import os
from rest_framework.response import Response
from jwt import JWT, jwk_from_dict, jwk_from_pem
from datetime import datetime, timedelta, timezone
from jwt.utils import get_int_from_datetime
#pub_key、pri_key使用下面这个网址生成,然后直接粘贴进来就ok了
#https://mkjwk.org/?spm=a2c4g.11186623.2.20.2aed167chumlVx
# 根据用户传递的值用私钥加密,签名,公钥解密、解签
class JwtToken:
pub_key = {自己生成 }
pri_key = { 自己生成}
def encode_token(self, data, set_time=240):
# with open("./pri.pem", 'rb') as f:
# jwk_from_pem(f.read())
signing_key = jwk_from_dict(self.pri_key)
instance = JWT()
# print(signing_key.to_dict())
data['iat'] = get_int_from_datetime(datetime.now(timezone.utc))
data['exp'] = get_int_from_datetime(datetime.now(timezone.utc) + timedelta(hours=set_time))
# print(data)
return instance.encode(payload=data, key=signing_key, alg='RS256')
def decode_token(self, data):
verifying_key = jwk_from_dict(self.pub_key)
instance = JWT()
return instance.decode(data, verifying_key, do_time_check=True)
# 哈希密码
def pwd_hash(val):
slat = 'zheshiyan'
md5 = hashlib.md5()
# print(val, slat)
md5.update((val+slat).encode('utf-8'))
return md5.hexdigest()
#重写返回值格式
def info(data='', status=1, message='', headers=None):
res = Response()
res.data = {
'status': status,
'message': message,
'data': data
}
if headers:
for k, v in headers.items():
res[k] = v
return res
这个登录没有写serializers,大概就是这样实现。