From 7e4bc7f87b5580f00219dd8fbfe86df851f2a99b Mon Sep 17 00:00:00 2001 From: waner Date: Thu, 24 Jul 2025 18:02:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=82=E6=95=B0=E8=8C=83?= =?UTF-8?q?=E5=9B=B4=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sunyard/util/AddressUtil.java | 70 +++++++++++++++++++ .../java/racal/sunyard/main/SydApi4j.java | 29 +++++++- src/test/java/sample/Test4NongxinCW.java | 59 ++++++++++------ 3 files changed, 133 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/sunyard/util/AddressUtil.java diff --git a/src/main/java/com/sunyard/util/AddressUtil.java b/src/main/java/com/sunyard/util/AddressUtil.java new file mode 100644 index 0000000..0b59d1f --- /dev/null +++ b/src/main/java/com/sunyard/util/AddressUtil.java @@ -0,0 +1,70 @@ +package com.sunyard.util; + +import java.util.regex.Pattern; + +public class AddressUtil { + // 处理带端口号的地址 + public static boolean isValidAddressWithPort(String address) { + if (address == null) { + return false; + } + + // 分离 IP:port 或 [IPv6]:port + String[] parts; + if (address.startsWith("[") && address.contains("]:")) { + parts = address.split("\\]:", 2); + parts[0] = parts[0] + "]"; // 补全 IPv6 的括号 + } else { + parts = address.split(":", 2); + } + + if (parts.length != 2) { + return false; + } + + String ipPart = parts[0]; + String portPart = parts[1]; + + return isValidIP(ipPart) && + isValidPort(portPart); + } + + // IPv4 正则(允许 0-255) + private static final Pattern IPV4_PATTERN = Pattern.compile( + "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" + ); + + // IPv6 正则(包含缩写形式) + private static final Pattern IPV6_PATTERN = Pattern.compile( + "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$" + ); + + // 简化域名正则(允许字母、数字、连字符和点) + private static final Pattern DOMAIN_PATTERN = Pattern.compile( + "^([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,63}$" + ); + + public static boolean isValidIP(String ip) { + // 检查 IPv4 或 IPv6 + return IPV4_PATTERN.matcher(ip).matches() || + IPV6_PATTERN.matcher(ip).matches(); + } + + public static boolean isValidDomain(String domain) { + return DOMAIN_PATTERN.matcher(domain).matches(); + } + + public static boolean isValidPort(int port) { + return port >= 0 && port <= 65535; + } + + // 字符串形式的端口校验 + public static boolean isValidPort(String portStr) { + try { + int port = Integer.parseInt(portStr); + return port >= 0 && port <= 65535; + } catch (NumberFormatException e) { + return false; + } + } +} diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 9e106af..7d318cd 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -146,6 +146,15 @@ public class SydApi4j implements SydApi { Assert.notBlank(ip1, "主机IP不能为空"); Assert.notBlank(ip2, "备机IP不能为空"); Assert.notNull(port, "端口不能为空"); + if (!AddressUtil.isValidIP(ip1) || !AddressUtil.isValidIP(ip2)) { + throw new IllegalArgumentException("主备机ip格式有误"); + } + if (!AddressUtil.isValidPort(port)) { + throw new IllegalArgumentException("端口范围有误"); + } + if (timeout < 0 || timeout > 60000) { + throw new IllegalArgumentException("超时时间范围不正确"); + } SydApi4j.ha_ip1 = ip1; SydApi4j.ha_ip2 = ip2; SydApi4j.ha_port = port; @@ -1358,6 +1367,9 @@ public class SydApi4j implements SydApi { if (null == addressList || addressList.isEmpty()) { throw new IllegalArgumentException("签名服务器地址不能为空"); } + if (addressList.size() > 50) { + throw new IllegalArgumentException("签名服务器地址数量不大于50"); + } if (null == cert || cert.length() == 0) { throw new IllegalArgumentException("证书不能为空"); } @@ -1365,7 +1377,7 @@ public class SydApi4j implements SydApi { throw new IllegalArgumentException("snmp配置不能为空"); } List> taskContexts = - addressList.stream().map(p -> createTaskContext(p, timeout, cert)).collect(Collectors.toList()); + addressList.stream().distinct().map(p -> createTaskContext(p, timeout, cert)).collect(Collectors.toList()); AsyncTaskExecutor executor = new AsyncTaskExecutor(); List> taskOutcomes = executor.execBatchTasks(taskContexts); executor.shutdown(); @@ -1429,6 +1441,9 @@ public class SydApi4j implements SydApi { private String importCertToServer(String address, int timeout, String cert) { //address 格式为 ip:port,拆分成ip和port,需要进行格式判断 + if (!AddressUtil.isValidAddressWithPort(address)) { + throw new IllegalArgumentException("地址格式有误:" + address); + } String[] addressParts = address.split(":"); String ip = addressParts[0]; int port = Integer.parseInt(addressParts[1]); @@ -2674,7 +2689,17 @@ public class SydApi4j implements SydApi { @Override synchronized public SydApi connect(String ip, int port, String pwd, int timeout) { - + Assert.notBlank(ip, "IP不能为空"); + Assert.notNull(port, "端口不能为空"); + if (!AddressUtil.isValidIP(ip)) { + throw new IllegalArgumentException("ip格式有误"); + } + if (!AddressUtil.isValidPort(port)) { + throw new IllegalArgumentException("端口范围有误"); + } + if (timeout < 0 || timeout > 60000) { + throw new IllegalArgumentException("超时时间范围不正确"); + } // if (null != ha_ip2) { // throw new SydApiException("双机热备模式不用调用此方法", -1); // } diff --git a/src/test/java/sample/Test4NongxinCW.java b/src/test/java/sample/Test4NongxinCW.java index 4554a16..a167d19 100644 --- a/src/test/java/sample/Test4NongxinCW.java +++ b/src/test/java/sample/Test4NongxinCW.java @@ -60,10 +60,10 @@ public class Test4NongxinCW { // System.out.println("SM2数据验签:"+nakedVerify1 ); for (int i = 0; i < 10000; i++) { byte[] nakedSign = api.SYD_NakedSign(orgData,SM2dn); -// System.out.println("SM2签名:"+ Util.bytes2HexString(nakedSign)); - byte[] nakedSign1 = api.SYD_NakedSignAll(4,orgData, SM2dn); + System.out.println("SM2签名:"+ Util.encodeBase64(nakedSign)); +// byte[] nakedSign1 = api.SYD_NakedSignAll(4,orgData, SM2dn); // System.out.println("SM2大数据裸签:"+ Util.bytes2HexString(nakedSign1)); - boolean nakedVerify1 = api.SYD_NakedVerifyAll(4,orgData, nakedSign1, SM2dn); +// boolean nakedVerify1 = api.SYD_NakedVerifyAll(4,orgData, nakedSign1, SM2dn); // System.out.println("SM2数据验签:"+nakedVerify1 ); } } @@ -348,25 +348,30 @@ public class Test4NongxinCW { StopWatch stopWatch = new StopWatch(); stopWatch.start(); String cert = "-----BEGIN CERTIFICATE-----\n" + - "MIICMDCCAdagAwIBAgIJAOWoGwJCnjlLMAoGCCqBHM9VAYN1MGcxCzAJBgNVBAYT\n" + - "AkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdIYWlEaWFuMRMwEQYDVQQK\n" + - "DApHTUNlcnQub3JnMR8wHQYDVQQDDBZHTUNlcnQgR00gUm9vdCBDQSAtIDAxMB4X\n" + - "DTI1MDUxMzAyMzUxM1oXDTI2MDUxMzAyMzUxM1owRTELMAkGA1UEBgwCQ04xCzAJ\n" + - "BgNVBAgMAnp6MQswCQYDVQQHDAJ6ejEMMAoGA1UECgwDenp6MQ4wDAYDVQQDDAV6\n" + - "enp6ejBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABK5fyRSACWPIBBr/3U+qvjvp\n" + - "niropv2PrA3ZLU1bG8vQpwAEMA0kwyqGgXURBPbvWdAhN7s9wfvHbJyMd9CMZGqj\n" + - "gYwwgYkwDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCB4AwLAYJYIZIAYb4QgENBB8W\n" + - "HUdNQ2VydC5vcmcgU2lnbmVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSQB7UUqEuG\n" + - "kl4mrx3MAhKTptfbYjAfBgNVHSMEGDAWgBR/Wl47AIRZKg+YvqEObzmVQxBNBzAK\n" + - "BggqgRzPVQGDdQNIADBFAiEA4kgTdn/iA/XYfjTEeOcELwBXd0tTFghkpfP8DhBF\n" + - "KFQCIAXZTL6VPtW67tM/DF4ZgFt5S/YIiFombKa2bWOfL81u\n" + + "MIIC2TCCAn2gAwIBAgIFIGh5YWAwDAYIKoEcz1UBg3UFADBdMQswCQYDVQQGEwJD\n" + + "TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y\n" + + "aXR5MRwwGgYDVQQDDBNDRkNBIFRFU1QgU00yIE9DQTExMB4XDTI0MDQwOTAxMTAy\n" + + "M1oXDTI1MTEzMDAxMTAyM1owgY4xCzAJBgNVBAYTAmNuMR8wHQYDVQQKDBZDRkNB\n" + + "IENTIFRFU1QgU00yIE9DQTExMQ0wCwYDVQQLDARERU1QMRkwFwYDVQQLDBBPcmdh\n" + + "bml6YXRpb25hbC0xMTQwMgYDVQQDDCswNTFAM0MzMTIyOTM0MDAwMDE0QEMzMTIy\n" + + "OTM0MDAwMDE0QDAwMDAwMDAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEyW/R\n" + + "iEfheoKHHf8UGA8D8dMRIKiGr1M3kId/f1mfWsTX/BTH8+FmruZxfGZAXcSGcn5Z\n" + + "gR582ck7YO2bhDcap6OB9TCB8jAfBgNVHSMEGDAWgBS+pn5NPXyPoFXmwS8JLiwg\n" + + "Q7NCfzBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6\n" + + "Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuG\n" + + "KWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9TTTIvY3JsMjkyNzMuY3JsMAsGA1Ud\n" + + "DwQEAwID6DAdBgNVHQ4EFgQU1K07X7clXMkYBI3JblkykKilnskwHQYDVR0lBBYw\n" + + "FAYIKwYBBQUHAwIGCCsGAQUFBwMEMAwGCCqBHM9VAYN1BQADSAAwRQIhAL8uWl4K\n" + + "hUEIUnSsM0RlUn4aSkK3R0QFpqdBu7AYCtXcAiB5tIOkP1ycAtp0W3mSHPabAgUq\n" + + "dHXEO3AzKABKxIAH7Q==\n" + "-----END CERTIFICATE-----"; List masterNodes = new ArrayList<>(); // masterNodes.add("172.16.18.99:8889"); // masterNodes.add("172.16.18.5:8889"); - masterNodes.add("172.1.41.96:8889"); -// masterNodes.add("172.1.41.196:8889"); -// masterNodes.add("172.16.18.8:8889"); + masterNodes.add("172.1.41.139:8889"); +// masterNodes.add("172.1.41.196:8889333"); +// masterNodes.add("172.16.18.89"); +// masterNodes.add("172.16.18.89"); int timeout = 3000; Map map = new HashMap<>(); map.put("snmp.target.ip", "172.1.41.191"); @@ -534,11 +539,15 @@ public class Test4NongxinCW { // byte[] oData = (byte[]) denSM2.get("oData"); // System.out.println("SM2信封解密:"+Util.bytes2HexString(oData)); - String SM2dn = "C=CN,ST=北京,L=北京,O=信雅达,OU=双证,CN=172.1.40.188"; - String ivHex = "31323334353637383132333435363738"; - RetWrap genByDn = api.generateDEByDnICBC(SM2dn, ivHex,orgData,1); - String cipherKey1 = (String) genByDn.get(SydApi.RET_CIPHER_KEY); - System.out.println("SM2数字信封: " +cipherKey1); + String sign = "MEYCIQDo11zaTBYiesXP5Xk2BWHoBI2u+F3W2Kb9DFfDQEntLwIhANzKl8eV3M1cYxrZbsiP2I02HQBQFrkyeUhwW1iVKSt2"; + byte[] s1 = Util.decodeBase64(sign); + System.out.println(Util.bytes2HexString(s1)); + +// String SM2dn = "C=CN,ST=北京,L=北京,O=信雅达,OU=双证,CN=172.1.40.188"; +// String ivHex = "31323334353637383132333435363738"; +// RetWrap genByDn = api.generateDEByDnICBC(SM2dn, ivHex,orgData,1); +// String cipherKey1 = (String) genByDn.get(SydApi.RET_CIPHER_KEY); +// System.out.println("SM2数字信封: " +cipherKey1); } @Test @@ -565,6 +574,10 @@ public class Test4NongxinCW { "MIICujCCAl6gAwIBAgIFEFeGNUIwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjMxMDI2MDYwMDU5WhcNMjgxMDI2MDYwMDU5WjByMQswCQYDVQQGEwJjbjEXMBUGA1UECgwOQ0ZDQSBURVNUIE9DQTExDTALBgNVBAsMBERFTVAxGTAXBgNVBAsMEE9yZ2FuaXphdGlvbmFsLTExIDAeBgNVBAMMFzA0MUBaREVNUEBERU1QQDAwMDAwMDAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE3NOLwnCvPxeZxS5lUSl+fxojdYwV1mD5eDGOkPeATl88oW0Q1PuBd0aQ29HmufRamZb2BlfLhjcgS5TsKlX4qqOB9DCB8TAfBgNVHSMEGDAWgBRr/hjaj0I6prhtsy6Igzo0osEw4TBIBgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly91Y3JsLmNmY2EuY29tLmNuL1NNMi9jcmw1Mzg2My5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSElGKzsZJ04RMd60sFqiHpxl9/njAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANIADBFAiEAjmCCIlDNdXw0qRZe7oYrkel4wTpg++c/C+MKLbPfRpgCIEVyrM68qeuVmaFZ5ZA3TtUXQg1RYQjz/5yhl/3jhdQ9"; byte[] s = Base64.getDecoder().decode(cert); System.out.println(convertToPem(s)); + + String ss = "2025071700064382|2025-06-21T15:39:47|102100088898|102100088898|402361018886|402361018886|BEPS|DM00|202507170013|010000|123456789123456789|1|2025071700064387|王二|地址908|6232208340101760984|402361018886|402361018886|CNY0.05|"; + byte[] sss = ss.getBytes(); + System.out.println(Util.bytes2HexString(sss)); } public String convertToPem(byte[] derCert) throws Exception {