Bläddra i källkod

检查登录态

locky 8 månader sedan
förälder
incheckning
6963e1fdaa
2 ändrade filer med 64 tillägg och 5 borttagningar
  1. 63 5
      Controller/WeChatMiniProgram/UserController.py
  2. 1 0
      Object/Enums/WeChatEnum.py

+ 63 - 5
Controller/WeChatMiniProgram/UserController.py

@@ -2,6 +2,7 @@
 # @File      : UserController.py
 # @Time      : 2024/11/27 16:35
 import hashlib
+import hmac
 import os
 import time
 
@@ -35,7 +36,42 @@ class EquipmentFamilyView(View):
         elif operation == 'login':
             return self.login(request_dict, response)
         else:
-            return response.json(414)
+            valid = self.check_session_key(request)
+            if not valid:
+                return response.json(309)
+
+    @classmethod
+    def check_session_key(cls, request):
+        """
+        校验 session_key 是否有效
+        https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/checkSessionKey.html
+        @return: bool
+        """
+        try:
+            login_status = request.META.get('HTTP_AUTHORIZATION')
+            if not  login_status:
+                return False
+            wechat_mini_program_qs = WeChatMiniProgram.objects.filter(login_status=login_status). \
+                values('openid', 'session_key')
+            if not wechat_mini_program_qs.exists():
+                return False
+            openid = wechat_mini_program_qs[0]['openid']
+            session_key = wechat_mini_program_qs[0]['session_key']
+            signature = cls.generate_signature(session_key)
+            access_token = cls.get_access_token()
+            params = {
+                'openid': openid,
+                'access_token': access_token,
+                'signature': signature,
+                'sig_method': 'hmac_sha256'
+            }
+            r = requests.get(url=WeChatMiniProgramAPIEnum.checkSessionKeyAPI.value, params=params, timeout=5)
+            result = eval(r.content)
+            errcode = result.get('errcode')
+            assert errcode == 0
+            return True
+        except Exception as e:
+            return False
 
     @staticmethod
     def get_access_token():
@@ -130,10 +166,16 @@ class EquipmentFamilyView(View):
             # 生成登录态
             login_status = cls.generate_login_status(openid, session_key)
             now_time = int(time.time())
-            WeChatMiniProgram.objects.create(
-                login_status=login_status, openid=openid, unionid=unionid, session_key=session_key,
-                created_time=now_time, updated_time=now_time
-            )
+            wechat_mini_program_qs = WeChatMiniProgram.objects.filter(openid=openid)
+            if wechat_mini_program_qs.exists():
+                wechat_mini_program_qs.update(
+                    login_status=login_status, session_key=session_key, updated_time=now_time
+                )
+            else:
+                WeChatMiniProgram.objects.create(
+                    login_status=login_status, openid=openid, unionid=unionid, session_key=session_key,
+                    created_time=now_time, updated_time=now_time
+                )
             res = {
                 'login_status': login_status
             }
@@ -158,3 +200,19 @@ class EquipmentFamilyView(View):
         # 获取十六进制格式的哈希值
         login_status = hash_object.hexdigest()
         return login_status
+
+    @staticmethod
+    def generate_signature(session_key):
+        """
+        用户登录态签名,用session_key对空字符串签名得到的结果。即 signature = hmac_sha256(session_key, "")
+        @param session_key:
+        @return: signature
+        """
+        # 将session_key和要签名的数据(这里是空字符串)转换为字节类型
+        session_key_bytes = session_key.encode('utf-8')
+        data = b""  # 空字符串转换为字节类型
+        # 创建一个新的hmac对象,使用sha256作为hash函数
+        hmac_object = hmac.new(session_key_bytes, data, hashlib.sha256)
+        # 获取十六进制格式的签名结果
+        signature = hmac_object.hexdigest()
+        return signature

+ 1 - 0
Object/Enums/WeChatEnum.py

@@ -16,3 +16,4 @@ class WeChatMiniProgramAPIEnum(IntEnum):
     getAccessTokenAPI = 'https://api.weixin.qq.com/cgi-bin/token'
     getPhoneNumberAPI = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={}'
     code2SessionAPI = 'https://api.weixin.qq.com/sns/jscode2session'
+    checkSessionKeyAPI = 'https://api.weixin.qq.com/wxa/checksession'