mirror of
https://github.com/LamGC/Oracle-Sentry.git
synced 2025-04-29 22:27:34 +00:00
fact: 添加 SSH 端口配置项.
添加 SSH 端口配置项以允许自定义 SSH 连接端口. 本次提交也补充了相应的测试项, 覆盖率 100%.
This commit is contained in:
parent
59f1f3e57a
commit
984576f5e1
@ -65,7 +65,8 @@ public class InstanceSsh implements AutoCloseable {
|
|||||||
if (instancePublicIps.stream().findFirst().isEmpty()) {
|
if (instancePublicIps.stream().findFirst().isEmpty()) {
|
||||||
throw new IllegalStateException("Instance has no public IP available.");
|
throw new IllegalStateException("Instance has no public IP available.");
|
||||||
}
|
}
|
||||||
String connectUri = "ssh://" + authInfo.getUsername() + "@" + instancePublicIps.stream().findFirst().get() + ":22";
|
String connectUri = "ssh://" + authInfo.getUsername() + "@" +
|
||||||
|
instancePublicIps.stream().findFirst().get() + ":" + authInfo.getPort();
|
||||||
log.info("SSH 正在连接: {}", connectUri);
|
log.info("SSH 正在连接: {}", connectUri);
|
||||||
ConnectFuture connect = sshClient.connect(connectUri);
|
ConnectFuture connect = sshClient.connect(connectUri);
|
||||||
connect.verify();
|
connect.verify();
|
||||||
|
@ -15,11 +15,8 @@ public abstract class SshAuthInfo {
|
|||||||
private final static Logger log = LoggerFactory.getLogger(SshAuthInfo.class);
|
private final static Logger log = LoggerFactory.getLogger(SshAuthInfo.class);
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
/**
|
|
||||||
* 使用 Sha256 计算的密钥指纹.
|
|
||||||
*/
|
|
||||||
private PublicKey serverKey;
|
private PublicKey serverKey;
|
||||||
|
private int port;
|
||||||
private SshAuthIdentityProvider provider;
|
private SshAuthIdentityProvider provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,6 +62,22 @@ public abstract class SshAuthInfo {
|
|||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 SSH 连接端口.
|
||||||
|
* @param port SSH 端口号.
|
||||||
|
*/
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 SSH 端口号.
|
||||||
|
* @return 返回 SSH 端口号.
|
||||||
|
*/
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 SSH 认证配置提供器.
|
* 设置 SSH 认证配置提供器.
|
||||||
* <p> 设置后, 可在首次连接认证通过后, 保存服务器公钥到文件中.
|
* <p> 设置后, 可在首次连接认证通过后, 保存服务器公钥到文件中.
|
||||||
|
@ -56,6 +56,24 @@ public final class SshAuthInfoSerializer implements JsonSerializer<SshAuthInfo>,
|
|||||||
throw new JsonParseException("Unsupported authentication type: " + authType);
|
throw new JsonParseException("Unsupported authentication type: " + authType);
|
||||||
}
|
}
|
||||||
info.setUsername(getFieldToStringOrFail(infoObject, "username"));
|
info.setUsername(getFieldToStringOrFail(infoObject, "username"));
|
||||||
|
String portStr = getFieldToString(infoObject, "port");
|
||||||
|
if (portStr != null) {
|
||||||
|
try {
|
||||||
|
int port = Integer.parseInt(portStr);
|
||||||
|
if (checkPortNumber(port)) {
|
||||||
|
info.setPort(port);
|
||||||
|
} else {
|
||||||
|
log.warn("端口号非法, 将使用默认端口号.(Input: {})", port);
|
||||||
|
info.setPort(22);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.warn("端口号无法转换成数字, 端口号将使用默认端口号.(Input: {})", portStr);
|
||||||
|
info.setPort(22);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info.setPort(22);
|
||||||
|
}
|
||||||
|
|
||||||
String serverKeyStr = getFieldToString(infoObject, "serverKey");
|
String serverKeyStr = getFieldToString(infoObject, "serverKey");
|
||||||
if (!Strings.isNullOrEmpty(serverKeyStr)) {
|
if (!Strings.isNullOrEmpty(serverKeyStr)) {
|
||||||
try {
|
try {
|
||||||
@ -88,6 +106,7 @@ public final class SshAuthInfoSerializer implements JsonSerializer<SshAuthInfo>,
|
|||||||
|
|
||||||
json.addProperty("authType", src.getType().toString());
|
json.addProperty("authType", src.getType().toString());
|
||||||
json.addProperty("username", src.getUsername());
|
json.addProperty("username", src.getUsername());
|
||||||
|
json.addProperty("port", src.getPort());
|
||||||
if (src.getServerKey() != null) {
|
if (src.getServerKey() != null) {
|
||||||
json.addProperty("serverKey", encodeSshPublicKey(src.getServerKey()));
|
json.addProperty("serverKey", encodeSshPublicKey(src.getServerKey()));
|
||||||
} else {
|
} else {
|
||||||
@ -96,6 +115,10 @@ public final class SshAuthInfoSerializer implements JsonSerializer<SshAuthInfo>,
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkPortNumber(int port) {
|
||||||
|
return port >= 0 && port <= 65535;
|
||||||
|
}
|
||||||
|
|
||||||
private String getFieldToStringOrFail(JsonObject object, String field) {
|
private String getFieldToStringOrFail(JsonObject object, String field) {
|
||||||
if (!object.has(field) || !object.get(field).isJsonPrimitive()) {
|
if (!object.has(field) || !object.get(field).isJsonPrimitive()) {
|
||||||
throw new JsonParseException("Missing field: " + field);
|
throw new JsonParseException("Missing field: " + field);
|
||||||
|
@ -44,10 +44,6 @@ class SshAuthInfoSerializerTest {
|
|||||||
return gson.fromJson(new InputStreamReader(resource, StandardCharsets.UTF_8), JsonObject.class);
|
return gson.fromJson(new InputStreamReader(resource, StandardCharsets.UTF_8), JsonObject.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchTestsInfo(String name, JsonObject object) {
|
|
||||||
return getTestsInfo(name).equals(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deserializePasswordTest() {
|
public void deserializePasswordTest() {
|
||||||
SshAuthInfo info = gson.fromJson(getTestsInfo("StandardPassword"), SshAuthInfo.class);
|
SshAuthInfo info = gson.fromJson(getTestsInfo("StandardPassword"), SshAuthInfo.class);
|
||||||
@ -71,6 +67,39 @@ class SshAuthInfoSerializerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializeBadPortNumberTest() {
|
||||||
|
SshAuthInfo info = gson.fromJson(getTestsInfo("BadPortValue-NonNumber"), SshAuthInfo.class);
|
||||||
|
|
||||||
|
assertTrue(info instanceof PasswordAuthInfo);
|
||||||
|
assertEquals("opc", info.getUsername());
|
||||||
|
assertEquals("123456", ((PasswordAuthInfo) info).getPassword());
|
||||||
|
assertEquals("SHA256:qBu2jRXM6Wog/jWUJJ0WLTMb3UdDGAmYEVZQNZdFZNM", KeyUtils.getFingerPrint(info.getServerKey()));
|
||||||
|
assertEquals(22, info.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializePortNumberOutOfBoundTest() {
|
||||||
|
SshAuthInfo info = gson.fromJson(getTestsInfo("BadPortValue-OutOfBound"), SshAuthInfo.class);
|
||||||
|
|
||||||
|
assertTrue(info instanceof PasswordAuthInfo);
|
||||||
|
assertEquals("opc", info.getUsername());
|
||||||
|
assertEquals("123456", ((PasswordAuthInfo) info).getPassword());
|
||||||
|
assertEquals("SHA256:qBu2jRXM6Wog/jWUJJ0WLTMb3UdDGAmYEVZQNZdFZNM", KeyUtils.getFingerPrint(info.getServerKey()));
|
||||||
|
assertEquals(22, info.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializePortNumberOutOfBoundMinusTest() {
|
||||||
|
SshAuthInfo info = gson.fromJson(getTestsInfo("BadPortValue-OutOfBound-minus"), SshAuthInfo.class);
|
||||||
|
|
||||||
|
assertTrue(info instanceof PasswordAuthInfo);
|
||||||
|
assertEquals("opc", info.getUsername());
|
||||||
|
assertEquals("123456", ((PasswordAuthInfo) info).getPassword());
|
||||||
|
assertEquals("SHA256:qBu2jRXM6Wog/jWUJJ0WLTMb3UdDGAmYEVZQNZdFZNM", KeyUtils.getFingerPrint(info.getServerKey()));
|
||||||
|
assertEquals(22, info.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deserializeUnsupportedTest() {
|
public void deserializeUnsupportedTest() {
|
||||||
assertThrows(JsonParseException.class, () ->
|
assertThrows(JsonParseException.class, () ->
|
||||||
@ -107,10 +136,17 @@ class SshAuthInfoSerializerTest {
|
|||||||
gson.fromJson(getTestsInfo("UnsupportedJsonType"), SshAuthInfo.class));
|
gson.fromJson(getTestsInfo("UnsupportedJsonType"), SshAuthInfo.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializeBadRequiredFieldJsonTypeTest() {
|
||||||
|
assertThrows(JsonParseException.class, () ->
|
||||||
|
gson.fromJson(getTestsInfo("BadRequiredFieldType"), SshAuthInfo.class));
|
||||||
|
}
|
||||||
|
|
||||||
private void initialSshAuthInfo(SshAuthInfo info) {
|
private void initialSshAuthInfo(SshAuthInfo info) {
|
||||||
try {
|
try {
|
||||||
KeyPair pair = KeyUtils.generateKeyPair("ssh-rsa", 3072);
|
KeyPair pair = KeyUtils.generateKeyPair("ssh-rsa", 3072);
|
||||||
info.setServerKey(pair.getPublic());
|
info.setServerKey(pair.getPublic());
|
||||||
|
info.setPort(new Random().nextInt(65536));
|
||||||
info.setUsername("linux");
|
info.setUsername("linux");
|
||||||
if (info instanceof PasswordAuthInfo psw) {
|
if (info instanceof PasswordAuthInfo psw) {
|
||||||
psw.setPassword(String.valueOf(new Random().nextLong()));
|
psw.setPassword(String.valueOf(new Random().nextLong()));
|
||||||
@ -149,6 +185,7 @@ class SshAuthInfoSerializerTest {
|
|||||||
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
||||||
assertEquals(KeyUtils.getFingerPrint(info.getServerKey()),
|
assertEquals(KeyUtils.getFingerPrint(info.getServerKey()),
|
||||||
KeyUtils.getFingerPrint(decodeSshPublicKey(getOrFailField(json, "serverKey"))));
|
KeyUtils.getFingerPrint(decodeSshPublicKey(getOrFailField(json, "serverKey"))));
|
||||||
|
assertEquals(info.getPort(), Integer.parseInt(getOrFailField(json, "port")));
|
||||||
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
||||||
|
|
||||||
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
||||||
@ -164,6 +201,7 @@ class SshAuthInfoSerializerTest {
|
|||||||
assertEquals(KeyUtils.getFingerPrint(info.getServerKey()),
|
assertEquals(KeyUtils.getFingerPrint(info.getServerKey()),
|
||||||
KeyUtils.getFingerPrint(decodeSshPublicKey(getOrFailField(json, "serverKey"))));
|
KeyUtils.getFingerPrint(decodeSshPublicKey(getOrFailField(json, "serverKey"))));
|
||||||
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
||||||
|
assertEquals(info.getPort(), Integer.parseInt(getOrFailField(json, "port")));
|
||||||
|
|
||||||
assertEquals(info.getPrivateKeyPath().getCanonicalFile(), new File(getOrFailField(json, "privateKeyPath")));
|
assertEquals(info.getPrivateKeyPath().getCanonicalFile(), new File(getOrFailField(json, "privateKeyPath")));
|
||||||
assertEquals(info.getKeyPassword(), getOrFailField(json, "keyPassword"));
|
assertEquals(info.getKeyPassword(), getOrFailField(json, "keyPassword"));
|
||||||
@ -180,6 +218,7 @@ class SshAuthInfoSerializerTest {
|
|||||||
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
||||||
assertTrue(json.get("serverKey").isJsonNull());
|
assertTrue(json.get("serverKey").isJsonNull());
|
||||||
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
||||||
|
assertEquals(info.getPort(), Integer.parseInt(getOrFailField(json, "port")));
|
||||||
|
|
||||||
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
||||||
}
|
}
|
||||||
@ -212,6 +251,7 @@ class SshAuthInfoSerializerTest {
|
|||||||
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
assertEquals(SshAuthInfo.AuthType.PASSWORD.name(), getOrFailField(json, "authType"));
|
||||||
assertTrue(json.get("serverKey").isJsonNull());
|
assertTrue(json.get("serverKey").isJsonNull());
|
||||||
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
assertEquals(info.getUsername(), getOrFailField(json, "username"));
|
||||||
|
assertEquals(info.getPort(), Integer.parseInt(getOrFailField(json, "port")));
|
||||||
|
|
||||||
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
assertEquals(info.getPassword(), getOrFailField(json, "password"));
|
||||||
}
|
}
|
||||||
|
7
src/test/resources/ssh-auth/BadPortValue-NonNumber.json
Normal file
7
src/test/resources/ssh-auth/BadPortValue-NonNumber.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"username": "opc",
|
||||||
|
"authType": "password",
|
||||||
|
"port": "test",
|
||||||
|
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"username": "opc",
|
||||||
|
"authType": "password",
|
||||||
|
"port": "-22",
|
||||||
|
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
7
src/test/resources/ssh-auth/BadPortValue-OutOfBound.json
Normal file
7
src/test/resources/ssh-auth/BadPortValue-OutOfBound.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"username": "opc",
|
||||||
|
"authType": "password",
|
||||||
|
"port": "1000000",
|
||||||
|
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
9
src/test/resources/ssh-auth/BadRequiredFieldType.json
Normal file
9
src/test/resources/ssh-auth/BadRequiredFieldType.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"username": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"authType": "password",
|
||||||
|
"port": 22,
|
||||||
|
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
||||||
|
"password": "123456"
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"username": "opc",
|
"username": "opc",
|
||||||
"authType": "password",
|
"authType": "password",
|
||||||
|
"port": 22,
|
||||||
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
"serverKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/NGFFKkchNdE8HDE9WHGIcw97ZVOP5edY7drtRQn0xSSG6uLu08T36B8IWT+XJdg45/YMmcuVSzsG1QZs/R3s0URVUhsWjwdezWDeWeBHt8/6TGl2AsgA0iXSAOeRNldhZlITFvWoBEv2wElNjCTsEGo5bBp3rVPqqZNJFUs+FR9s/uVgmFqe7HGhuKhhk7BrRThJ/NcgDRicMQ4yXU3Hl++pG54TVLH+0HmgWg312XNAWtzw2iRmKBAuu2I4pP1TRp93K/lbD7QU8k8W7QcyGSAc73nZrhyzYVMko5wQGt4/vGpchOw7ehkotSejTB1GSyhzBTZobA23For76YLzuVFOjF3lEvSh1QV30ysu0PREKLtY83ad0WHVFqVgJrFHkkXQrglN335BhGwhFzwyMpRxbD8HCDtz6VjpqwoKtd/ExQkcfaj/g10o28vRzHGyzUbCTe433V61fjSsC4Bikw15vTnQ3ZuyOzfyoCYUNpFcf1Wv+mkoWqn9xU8lGvk= Test-Server",
|
||||||
"password": "123456"
|
"password": "123456"
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user