Lors de l'utilisation du processeur BeanShell pour les signatures, il faut toujours configurer manuellement les champs de paramètres à signer.
Lors de l'ajout de nouvelles interfaces et des tests de fonctionnalités, logique, exceptions, sécurité et concurrence, les paramètres doivent être ajustés à chaque fois, ce qui nécessite de reconfigurer le script BeanShell. Parfois, des erreurs de signature échouent systématiquement. C'est extrêmement fatigant.
J'ai également envisé d'utiliser un fichier CSV pour paramétrer les valeurs, mais plusieusr problèmes sont apparus :
- Pour une même interface avec un même fichier CSV, la paramétrisation fonctionne, mais lorsque le nombre d'interfaces augmente et que le nombre de paramètres différents dépasse 50, la maintainance devient très difficile.
- Lorsque les interfaces sont modifiées, il faut mettre à jour à la fois la configuration CSV et l'interface, ce qui est très fastidieux.
J'ai donc rehcerché une solution pour extraire automatiquement les paramètres de la requête, les trier automatiquement, les concaténer, générer la chaîne à signer, puis signer automatiquement. Ainsi, peu importe comment les interfaces et les paramètres changent, le script de signature n'a pas besoin d'être modifié et peut être réutilisé.
Utilisons JSR233 pour implémenter ceci : on peut aussi utiliser un script BeanShell.
Concept :
Premièrement, extraire les paramètres de la requête :
GET : ---Pas encore trouvé de solution,欢迎大家提供意见. ^_^
POST :
Trier les paramètres par clé et les concaténer en chaîne à signer
Concaténer la chaîne avec un masque
Appeler la méthode de signature pour générer la chaîne signée
Définir la chaîne signée comme paramètre d'en-tête HTTP
- Extraction des paramètres de la requête :
//Récupérer les paramètres du body de la requête
Arguments args = sampler.getArguments();
//Convertir les paramètres récupérés en format chaîne
String jsonData = args.getArgument(0).getValue();
//Note : le 0 dans getArgument(0) permet généralement de récupérer
//les données du seul paramètre présent.
//Plusieurs colonnes de données n'apparaissent qu lors de la récupération des valeurs de retour
log.info(">>>>>>>>>>>{}", jsonData);
//Valeur de sortie : >>>>>>>>>>>{"userId":"123456","userType":"123","type":"1"}
- Trier les paramètres par clé et les concaténer
//Convertir la chaîne json récupérée en map via JSONObject
Map dataMap = JSONObject.parseObject(jsonData, Map.class);
StringBuilder signatureBuilder = StringBuilder();
//Récupérer l'ensemble des clés de la map
Set<String> keySet = dataMap.keySet();
//Convertir l'ensemble en tableau
Object[] keyArray = keySet.toArray();
//Trier le tableau
Arrays.sort(keyArray);
//Concaténer les champs
for (Object paramKey : keyArray) {
String paramValue = null == dataMap.get(paramKey) ? "" : dataMap.get(paramKey).toString();
signatureBuilder.append(paramKey + "=" + paramValue);
// Champ final similaire : type=1userId=123456userType=123
}
- Concaténer la chaîne avec le masque
//Concaténer le masque
String rawSignature = "SECRET_KEY" + signatureBuilder.toString();
- Appeler la méthode de signature pour générer le champ signé
//Appeler la méthode de signature pour générer la chaîne chiffrée
String signatureResult = new CryptoHelper().calculateMd5(rawSignature);
log.info("signature------------->{}",signatureResult);
- Définir le champ signé comme paramètre de signature HTTP
//Définir la chaîne signée comme paramètre d'en-tête HTTP
vars.put("signature", signatureResult);
Voici le code complet :
Le paquet de signature XXXXsign doit être obtenu auprès des développeurs. Le paquet fastjson.jar peut être téléchargé sur Internet, il est généralement inclus dans les dépendances Maven.
import java.util.Map;
import org.apache.jmeter.config.Arguments;
import com.alibaba.fastjson.JSONObject;
import CryptoHelper;
//Récupérer les paramètres du body de la requête
Arguments args = sampler.getArguments();
//Convertir les paramètres récupérés en format chaîne
String jsonData = args.getArgument(0).getValue();
//Note : le 0 dans getArgument(0) permet généralement de récupérer
//les données du seul paramètre présent.
//Plusieurs colonnes de données n'apparaissent qu lors de la récupération des valeurs de retour
log.info(">>>>>>>>>>>{}", jsonData);
//Valeur de sortie : >>>>>>>>>>>{"userId":"123456","userType":"123","type":"1"}
//Convertir la chaîne json récupérée en map via JSONObject
Map dataMap = JSONObject.parseObject(jsonData, Map.class);
StringBuilder signatureBuilder = StringBuilder();
//Récupérer l'ensemble des clés de la map
Set<String> keySet = dataMap.keySet();
//Convertir l'ensemble en tableau
Object[] keyArray = keySet.toArray();
//Trier le tableau
Arrays.sort(keyArray);
//Concaténer les champs
for (Object paramKey : keyArray) {
String paramValue = null == dataMap.get(paramKey) ? "" : dataMap.get(paramKey).toString();
signatureBuilder.append(paramKey + "=" + paramValue);
// Champ final similaire : type=1userId=123456userType=123
}
//Concaténer le masque
String rawSignature = "SECRET_KEY" + signatureBuilder.toString();
//Appeler la méthode de signature pour générer la chaîne chiffrée
String signatureResult = new CryptoHelper().calculateMd5(rawSignature);
log.info("signature------------->{}",signatureResult);
//Définir la chaîne signée comme paramètre d'en-tête HTTP
vars.put("signature", signatureResult);