背景
事情是这样的,老板的需求是想要将部分查询类的接口在部署之前先测试一遍,避免在测试环境上出现一些服务之间配置出现的不可预见的情况。众所周知,所有的接口都是需要针对 Token 进行验证的,那么我该如何在 MeterSphere 平台上模拟用户登录系统这个情况呢?如何获取到 Token 并且保存起来方便实用呢?这些都是我们的关键点,接下来跟随我的内容一步步进行解决
基本逻辑
所以我们需要在 MeterSphere 上面配置,模拟用户网页前端的操作,将用户的 密码 + 公钥 进行加密,最后将加密后的密码,放在请求的数据中,发送登录请求。最后将 Token 存放在变量里面。后面的接口请求的时候,直接在请求头中带上 token 进行验证的操作。
详情可以参考上图
如何模拟前端加密操作
Metersphere 是支持使用下面语言格式的脚本进行前置操作的,包括 beanshell py javascript 等
前端的密码加密逻辑是如何实现的
const JSEncrypt = require('jsencrypt'); // 加密库
// 3. RSA 加密函数(使用 jsencrypt 库)
function encryptWithPublicKey(publicKey, plaintext) {
const encrypt = new JSEncrypt();
// 设置公钥
encrypt.setPublicKey(publicKey);
// 执行加密 plaintext 是用户输入的密码,当然这里使用的密码就是正确的密码
const encrypted = encrypt.encrypt(plaintext);
console.log("加密后的密码:", encrypted);
return encrypted;
}
上面是前端这边将密码加密的逻辑,这里就不过多赘述了,逻辑其实很简单。
1. 获取公钥 + 判断逻辑
这里在 MeterSphere 第一步 获取公钥 的时候将请求接口获取到的公钥保存起来
对应起来代码的逻辑是 获取 publicKey 公钥
// 1. 从变量或属性中获取公钥(PEM 格式,需去除头部和尾部标记)
String publicKeyPEM = vars.get("publicKey");
if (publicKeyPEM == null || publicKeyPEM.isEmpty()) {
log.error("未找到 publicKey 变量");
vars.put("encryptedPassword", "");
return;
}
2. 处理公钥的格式,并且保存
公钥的格式,有前后的部分,基础操作逻辑
// 2. 处理 PEM 格式的公钥(移除头部、尾部和换行符)
publicKeyPEM = publicKeyPEM
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
// 3. 解码公钥
byte[] encodedKey = Base64.getDecoder().decode(publicKeyPEM);
// 4. 生成公钥对象
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
java.security.PublicKey publicKey = keyFactory.generatePublic(keySpec);
3. 将密码进行加密,并且保存成变量,后面的接口中使用
// 5. 初始化加密器
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 6. 加密密码 这里密码用用户真实的密码
String password = "xxxxxx";
byte[] encryptedBytes = cipher.doFinal(password.getBytes("UTF-8"));
// 7. 转换为 Base64 编码(便于在接口中传输)
String encryptedPassword = Base64.getEncoder().encodeToString(encryptedBytes);
// 8. 保存加密结果到变量,供后续接口使用 这里变量名需要和后续的步骤中的变量名匹配
vars.put("encryptedPassword", encryptedPassword);
log.info("密码加密成功,已保存到 encryptedPassword 变量**");
4. 使用 encryptedPassword 加密后的密码登录
这里将保存好的加密后的密码,登录到请求体中,发送请求
5. 接收到 返回的 Token 内容,保存成变量
6. 在后面的接口中使用 Token
这里使用的变量的方式是 ${} ,请求头的名称这里需要和后端的接口协议,可以个性化设置。
这里就已经完全满足好我们的需求了。
总结
完整脚本
// BeanShell 脚本:使用 RSA 公钥加密密码
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import java.util.Base64;
try {
// 1. 从变量或属性中获取公钥(PEM 格式,需去除头部和尾部标记)
String publicKeyPEM = vars.get("publicKey");
if (publicKeyPEM == null || publicKeyPEM.isEmpty()) {
log.error("未找到 publicKey 变量");
vars.put("encryptedPassword", "");
return;
}
// 2. 处理 PEM 格式的公钥(移除头部、尾部和换行符)
publicKeyPEM = publicKeyPEM
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replaceAll("\\s+", "");
// 3. 解码公钥
byte[] encodedKey = Base64.getDecoder().decode(publicKeyPEM);
// 4. 生成公钥对象
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
java.security.PublicKey publicKey = keyFactory.generatePublic(keySpec);
// 5. 初始化加密器
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 6. 加密密码
String password = "xxxxxxxxx";
byte[] encryptedBytes = cipher.doFinal(password.getBytes("UTF-8"));
// 7. 转换为 Base64 编码(便于在接口中传输)
String encryptedPassword = Base64.getEncoder().encodeToString(encryptedBytes);
// 8. 保存加密结果到变量,供后续接口使用
vars.put("encryptedPassword", encryptedPassword);
log.info("密码加密成功,已保存到 encryptedPassword 变量");
} catch (Exception e) {
log.error("加密过程发生错误: " + e.getMessage());
e.printStackTrace();
vars.put("encryptedPassword", ""); // 设置空值避免后续步骤出错
}
按照我们的步骤一步步进行配置,那么我们在 MeterSphere 上面配置的内容就已经完成好了。接下来我们将我们定义好的接口一个个写入场景中,这样我们就能满足好老板的需求。按照步骤来进行一步步的检查。后面我们可以分享关于编辑 删除 等接口使用后,如何进行数据回滚等话题。