微信小程序后端实现授权登录(3)

# 配置数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'wx', 'USER':'root', 'PASSWORD':'root', 'HOST':'127.0.0.1', 'PORT': 3306, 'OPTIONS': {'charset': 'utf8mb4'}, # 微信用户名可能有标签,所以用utf8mb4 } } # 配置 django-redis CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "PASSWORD": "", }, }, }

wx/settings.py

# 小程序开发者id AppId="..." # 小程序的AppSecret AppSecret="..." code2Session="https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code" pay_mchid ='...' pay_apikey = '...'

wx/wx_login.py

from app01.wx import settings import requests # 调用微信code2Session接口,换取用户唯一标识 OpenID 和 会话密钥 session_key def login(code): response = requests.get(settings.code2Session.format(settings.AppId,settings.AppSecret,code)) data = response.json() if data.get("openid"): return data else: return False

项目/views.py

from rest_framework.views import APIView from rest_framework.response import Response from app01.wx import wx_login from django.core.cache import cache from app01 import models import time, hashlib class Login(APIView): def post(self, request): param = request.data # 拿到小程序端提交的code if param.get('code'): # 调用微信code2Session接口,换取用户唯一标识 OpenID 和 会话密钥 session_key data = wx_login.login(param.get('code')) if data: # 将openid 和 session_key拼接 val = data['openid'] + "&" + data["session_key"] key = data["openid"] + str(int(time.time())) # 将 openid 加密 md5 = hashlib.md5() md5.update(key.encode("utf-8")) key = md5.hexdigest() # 保存到redis内存库,因为小程序端后续需要认证的操作会需要频繁校验 cache.set(key, val) has_user = models.Wxuser.objects.filter(openid=data['openid']).first() # 用户不存在则创建用户 if not has_user: models.Wxuser.objects.create(openid=data['openid']) return Response({ "code": 200, "msg": "ok", "data": {"login_key": key} # 返回给小程序端 }) else: return Response({"code": 401, "msg": "code无效"}) else: return Response({"code": 401, "msg": "缺少参数"})

用户信息授权

小程序端test.wxml

<!--用户信息授权--> <button open-type="getUserInfo" bindgetuserinfo="info">授权登录</button>

test.js

Page({ info: function (res) { // console.log(res) wx.checkSession({ success() { //session_key 未过期,并且在本生命周期一直有效 wx.getUserInfo({ success: function (res) { // console.log(res) wx.request({ url: app.globalData.Url + "/getinfo/", data: { "encryptedData": res.encryptedData, "iv": res.iv, "login_key": wx.getStorageSync("login_key") }, method: "POST", header: { "content-type": "application/json" }, success: function (res) { console.log(res) } }) } }) })

后端 django

wx/WXBizDataCrypt.py

import base64 import json from Crypto.Cipher import AES from app01.wx import settings class WXBizDataCrypt: def __init__(self, appId, sessionKey): self.appId = appId self.sessionKey = sessionKey def decrypt(self, encryptedData, iv): # base64 decode sessionKey = base64.b64decode(self.sessionKey) encryptedData = base64.b64decode(encryptedData) iv = base64.b64decode(iv) cipher = AES.new(sessionKey, AES.MODE_CBC, iv) decrypted = json.loads(self._unpad(cipher.decrypt(encryptedData))) if decrypted['watermark']['appid'] != self.appId: raise Exception('Invalid Buffer') return decrypted def _unpad(self, s): return s[:-ord(s[len(s)-1:])] @classmethod def getInfo(cls,encryptedData,iv,session_key): return cls(settings.AppId,session_key).decrypt(encryptedData, iv)

项目/serializer.py

from rest_framework.serializers import ModelSerializer from app01 import models class User_ser(ModelSerializer): class Meta: model=models.Wxuser fields="__all__"

项目/views.py

from app01.wx import WXBizDataCrypt from app01 import serializer from app01 import models class GetInfo(APIView): def post(self,request): param=request.data # 需要小程序端将 encryptedData iv login_key 的值传到后端 # encryptedData iv seesion_key 用于解密获取用户信息 # login_key 用于校验用户登录状态 if param['encryptedData'] and param['iv'] and param['login_key']: # 从redis中拿到login_key并切分拿到 openid 和 session_key openid,seesion_key=cache.get(param['login_key']).split("&") # 利用微信官方提供算法拿到用户的开放数据 data=WXBizDataCrypt.WXBizDataCrypt.getInfo(param['encryptedData'] ,param['iv'] ,seesion_key) save_data={ "name":data['nickName'], "avatar":data['avatarUrl'], "language":data['language'], "province":data['province'], "city":data['city'], "country":data['country'], } # 将拿到的用户信息更新到用户表中 models.Wxuser.objects.filter(openid=openid).update(**save_data) # 反序列化用户对象,并返回到小程序端 data=models.Wxuser.objects.filter(openid=openid).first() data=serializer.User_ser(instance=data,many=False).data return Response({"code":200,"msg":"缺少参数","data":data}) else: return Response({"code":200,"msg":"缺少参数"})

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6e855866c53a5ed8f9a6d1f6fff37928.html