Dans l'écosystème WeChat Mini-Program, la session_key est un élément crucial pour sécuriser les échanges entre le client, les serveurs de WeChat et votre propre backend. Cet article détaille comment maintenir la validité de cette clé et comment traiter les données chiffrées côté serveur.
1. Comprendre le mécanisme de validité de la session_key
La session_key agit comme une clé de chiffrement pour les données sensibles (comme les informations utilisateur ou les numéros de téléphone). Voici les règles essentielles à retenir :
- Renouvellement : L'appel à
wx.loginpeut invalider l'anciennesession_key. Il ne faut donc l'appeler que lorsque cela est strictement nécessaire. - Expiration : WeChat gère l'expiration de manière dynamique. Plus l'utilisateur est actif, plus la durée de vie est prolongée.
- Vérificasion : L'API
wx.checkSessionpermet de vérifier la validité de la session sans générer de nouvelle clé, évitant ainsi de rompre le cycle de connexion inutilement.
2. Implémentation de la stratégie de connexion (Frontend)
Pour garantir que les requêtes de déchiffrement ne 植物 échouent pas, nous devons vérifier l'état de la session avant d'envoyer des données chiffrées au serveur.
// app.js - Gestion globale de l'authentification
App({
onLaunch: function () {
this.performAuthSync();
},
performAuthSync: function () {
wx.login({
success: (res) => {
if (res.code) {
wx.request({
url: `${this.globalData.apiHost}/v1/auth/login`,
method: 'POST',
data: { auth_code: res.code },
success: (response) => {
wx.setStorageSync('user_token', response.data.token);
}
});
}
}
});
},
globalData: {
apiHost: "https://api.votre-domaine.com"
}
});
// index.js - Logique de récupération des données utilisateur
const appInstance = getApp();
Page({
processUserData: function (userInfoEvent) {
const { iv, encryptedData } = userInfoEvent.detail;
wx.checkSession({
success: () => {
// La session est valide, on envoie les données au backend
this.dispatchDecryption(iv, encryptedData);
},
fail: () => {
// Session expirée, on reconnecte puis on envoie
appInstance.performAuthSync();
// Optionnel : Ajouter une logique de retry ici
}
});
},
dispatchDecryption: function (iv, encryptedData) {
wx.request({
url: `${appInstance.globalData.apiHost}/v1/user/decrypt-profile`,
method: 'POST',
data: {
iv: iv,
cipher_text: encryptedData,
token: wx.getStorageSync('user_token')
},
success: (res) => {
console.log("Profil mis à jour :", res.data);
}
});
}
});
3. Déchiffrement des données côté serveur (Python/Django)
Le backend doit utiliser l'algorithme AES-128-CBC pour traiter le cipher_text fourni par le client. Voici une implémentation robuste utilisant pycryptodome.
# views.py - Point d'entrée de l'API
from rest_framework.views import APIView
from rest_framework.response import Response
from django.core.cache import cache
from .security import WeChatDataProcessor
class UserProfileView(APIView):
def post(self, request):
payload = request.data
token = payload.get('token')
iv = payload.get('iv')
encrypted_data = payload.get('cipher_text')
if not all([token, iv, encrypted_data]):
return Response({"error": "Paramètres manquants"}, status=400)
# Récupération de la session_key stockée lors du login
session_info = cache.get(token)
if not session_info:
return Response({"error": "Session invalide ou expirée"}, status=401)
session_key, openid = session_info.split("|")
try:
processor = WeChatDataProcessor(app_id="VOTRE_APP_ID", session_key=session_key)
decrypted_info = processor.decrypt_data(encrypted_data, iv)
# Mise à jour du profil utilisateur
# UserProfile.objects.filter(wechat_id=openid).update(nickname=decrypted_info['nickName'], ...)
return Response({"status": "success", "data": decrypted_info})
except Exception as e:
return Response({"error": str(e)}, status=500)
# security.py - Utilitaire de déchiffrement
import base64
import json
from Crypto.Cipher import AES
class WeChatDataProcessor:
def __init__(self, app_id, session_key):
self.app_id = app_id
self.session_key = base64.b64decode(session_key)
def decrypt_data(self, encrypted_data, iv):
encrypted_data = base64.b64decode(encrypted_data)
iv = base64.b64decode(iv)
cipher = AES.new(self.session_key, AES.MODE_CBC, iv)
decrypted_raw = cipher.decrypt(encrypted_data)
# Suppression du padding PKCS7
padding_len = decrypted_raw[-1]
decrypted_json = json.loads(decrypted_raw[:-padding_len].decode('utf-8'))
if decrypted_json['watermark']['appid'] != self.app_id:
raise ValueError("ID d'application non valide dans le filigrane")
return decrypted_json
4. Support des Emojis dans la base de données
Les pseudonymes des utilisateurs WeChat contiennent fréquemment des emojis. Pour éviter des erreurs lors de l'insertion en base de données (notamment avec MySQL), il est impératif d'utiliser le jeu de caractères utf8mb4 au lieu de utf8.
# settings.py - Configuration Django pour MySQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'wechat_db',
'USER': 'db_admin',
'PASSWORD': 'password_secure',
'HOST': 'localhost',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
'init_command': "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
},
}
}
Notes supplémentaires
Si votre environnement Python ne dispose pas des bibliothèques nécessaires pour les opérations cryptographiques, installez le paquet suivant :
pip install pycryptodome
Cette approche garantit que la communication reste fluide même si la session_key expire pendant que l'utilisateur navigue sur l'application, en automatisant la vérification et la récupération sans impact sur l'expérience utilisateur.