小程序session_key失效解决方案、后台解密个人数据信息

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

小程序session_key失效解决方案、后台解密个人数据信息

Jeff的技术栈   2020-03-13 我要评论
[TOC] # 一、登录会话密钥 session_key 有效性 开发者如果遇到因为 session_key 不正确而校验签名失败或解密失败,请关注下面几个与 session_key 有关的注意事项。 1. [wx.login](https:/https://img.qb5200.com/download-x/developers.weixin.qq.com/miniprogramhttps://img.qb5200.com/download-x/dev/api/open-api/login/wx.login.html) 调用时,用户的 session_key **可能**会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 [wx.login](https:/https://img.qb5200.com/download-x/developers.weixin.qq.com/miniprogramhttps://img.qb5200.com/download-x/dev/api/open-api/login/wx.login.html),并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 [wx.login](https:/https://img.qb5200.com/download-x/developers.weixin.qq.com/miniprogramhttps://img.qb5200.com/download-x/dev/api/open-api/login/wx.login.html),及时通过 [auth.code2Session](https:/https://img.qb5200.com/download-x/developers.weixin.qq.com/miniprogramhttps://img.qb5200.com/download-x/dev/api-backend/open-api/login/auth.code2Session.html) 接口更新服务器存储的 session_key。 2. 微信不会把 session_key 的有效期告知开发者。我们会根据用户使用小程序的行为对 session_key 进行续期。用户越频繁使用小程序,session_key 有效期越长。 3. 开发者在 session_key 失效时,可以通过重新执行登录流程获取有效的 session_key。使用接口 [wx.checkSession](https:/https://img.qb5200.com/download-x/developers.weixin.qq.com/miniprogramhttps://img.qb5200.com/download-x/dev/api/open-api/login/wx.checkSession.html)可以校验 session_key 是否有效,从而避免小程序反复执行登录流程。 4. 当开发者在实现自定义登录态时,可以考虑以 session_key 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。 # 二、解决登录session_key 的问题 通过wx.checkSession判断是否过期。 ``` 第一步:在生命周期中onLaunch调用一次写的登录方法 第二步:在其他地方通过wx.checkSession判断是否过期,如果过期再次调用登录方法,更新session_key ``` ## 案例:解决session_key 过期问题,发送个人信息后台解密 ```js # app.js中: //app.js App({ /* 当小程序初始话完成,会触发onlaunch(全局只触发一次) */ onLaunch: function () { // 登录 this.my_login() }, my_login:function(){ let that = this wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId console.log(res.code) wx.request({ url: that.globalData.baseurl + "login/", data: { "code": res.code }, method: "POST", success(e) { wx.setStorageSync('token', e.data.data.token) } }) } }) }, globalData: { userInfo: null, baseurl:"http://127.0.0.1:8000/" } }) # 页面js中: // 先拿到app全局对象 const app = getApp() user1:function (e) { wx.getSetting({ success(res) { if (res.authSetting['scope.userInfo']) { wx.getUserInfo({ success: (res) => { console.log("res",res) //这个res就是用户的信息 // 将数据发送后端 wx.request({ // 发送iv,encryptedData url: app.globalData.baseurl + "getinfo/", data:{ iv:res.iv, encryptedData: res.encryptedData, token:wx.getStorageSync("token") }, method:"POST", success:(e) =>{ console.log('后台返回的数据',e) } }) }, }) // 判断是否过期 wx.checkSession({ success() { //session_key 未过期,并且在本生命周期一直有效 }, fail() { // session_key 已经失效,需要重新执行登录流程 app.my_login() // 重新登录,更新session_key wx.getUserInfo({ success: (res) => { console.log("res啦啦啦", res) //这个res就是用户的信息 // 将数据发送后端 wx.request({ // 发送iv,encryptedData url: 'url', }) }, }) } }) } } }) } ``` ## 后端解密信息,存入数据库 ```python # 登录:略 # urls.py path('getinfo/', user.Info.as_view()), # user.py from django.core.cache import cache from api.models import Wxuser from api.wx import WXBizDataCrypt from api.my_ser import wx_user_ser from rest_framework.response import Response class Info(APIView): def post(self, request): param = request.data if param['iv'] and param.get("token") and param.get("encryptedData"): iv = param['iv'] encryptedData = param.get("encryptedData") session_key_openid = cache.get(param.get("token")) if session_key_openid: sessionKey, openid = session_key_openid.split("&") # 解密 user_info = WXBizDataCrypt.WXBizDataCrypt.get_info(sessionKey, encryptedData, iv) print('user_info', user_info) save_data = { "name": user_info['nickName'], "avatar": user_info['avatarUrl'], "language": user_info['language'], "province": user_info['province'], "city": user_info['city'], "country": user_info['country'], } # 把用户信息存入数据库 Wxuser.objects.filter(openid=openid).update(**save_data) # 测试:把童虎信息返回给前台 user = Wxuser.objects.filter(openid=openid).first() user = wx_user_ser(instance=user, many=False).data return Response({ "status": 0, "msg": "ok", "data": user }) else: return Response({"code": 2, "msg": "无效的token"}) else: return Response({"code": 1, "msg": "缺少参数"}) # 检测对字典排序 # WXBizDataCrypt文件,下载的解密,然后二次封装的 import base64 import json from Crypto.Cipher import AES from api.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 get_info(cls,sessionKey,encryptedData,iv): # appId = settings.AppId # sessionKey = sessionKey # encryptedData = encryptedData # iv = iv # # # 实例化这个类 WXBizDataCrypt # pc = cls(appId, sessionKey) # return pc.decrypt(encryptedData, iv) # 简化为: return cls(settings.AppId, sessionKey).decrypt(encryptedData, iv) ``` ## mysql数据库存表情设置 ![](https://img2020.cnblogs.com/blog/1736414/202003/1736414-20200313221019069-466149718.png) ```python 1.mysql数据库类型 2.配置:默认是utf8,3个字节。表情是4个字节,需要设置:'OPTIONS': {'charset': 'utf8mb4'}, import pymysql pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'python13', 'USER': 'root', 'PASSWORD': '123', 'HOST': 'localhost', 'PORT': 3306, 'OPTIONS': {'charset': 'utf8mb4'}, } } ``` # 三、后端,如何解析wx.getUserInfor中的用户信息。 ``` 1 我们用encryptedData和iv,进行解密,必须要用到session_key,所以用必须是登入状态。 2 但是session_key是有有效期。而且session_key的有效期,不是一个固定值,他是通过用户行为来决定,session_key的有效期时间。 3 但是我们可以通过wx.checkSession来判断有没有过期。 4 保证session_key没有过期的情况下。我们将iv,encryptedData,token(登入凭证)发送到后端. 5 后端使用官方提供的sdk,进行解密。 6 解密成功以后保存到数据,数据库的字符集一定要是utf8mb4,才能保存表情包 ``` 如官方的sdk没有Crypto包用下面的方法解决: ``` pip install pycryptodome ``` # 用户信息官方文档 # 数据加密官方文档

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们