diff --git a/rc-auth/src/main/java/com/red/circle/auth/common/LoginAccessValidationService.java b/rc-auth/src/main/java/com/red/circle/auth/common/LoginAccessValidationService.java index add9e10a..5562fda6 100644 --- a/rc-auth/src/main/java/com/red/circle/auth/common/LoginAccessValidationService.java +++ b/rc-auth/src/main/java/com/red/circle/auth/common/LoginAccessValidationService.java @@ -38,6 +38,12 @@ public class LoginAccessValidationService { private static final List ALLOWED_CHINA_REGIONS = List.of( "香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan" ); + private static final List BLOCKED_COUNTRY_CODES = List.of( + "HK", "MO", "SG" + ); + private static final List BLOCKED_COUNTRY_NAMES = List.of( + "香港", "澳门", "澳門", "Hong Kong", "Macau", "Macao", "新加坡", "Singapore" + ); private static final List IP_GEO_PROVIDERS = List.of( new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"), new IpGeoProvider("freeipapi", "https://freeipapi.com/api/json/%s"), @@ -144,7 +150,7 @@ public class LoginAccessValidationService { } private boolean isIpValidationFailed(String ip) { - return isMainlandChina(loadIpData(ip)); + return isBlockedIpRegion(loadIpData(ip)); } private boolean isZoneValidationFailed(String reqZone) { @@ -235,6 +241,10 @@ public class LoginAccessValidationService { }; } + static boolean isBlockedIpRegion(JSONObject dataObject) { + return isMainlandChina(dataObject) || isBlockedCountryOrRegion(dataObject); + } + static boolean isMainlandChina(JSONObject dataObject) { if (dataObject == null) { return false; @@ -251,6 +261,20 @@ public class LoginAccessValidationService { return StringUtils.isBlank(region) || !ALLOWED_CHINA_REGIONS.contains(region); } + private static boolean isBlockedCountryOrRegion(JSONObject dataObject) { + if (dataObject == null) { + return false; + } + String countryCode = dataObject.getString("country_id"); + if (StringUtils.isNotBlank(countryCode) + && BLOCKED_COUNTRY_CODES.contains(countryCode.trim().toUpperCase(Locale.ROOT))) { + return true; + } + String country = dataObject.getString("country"); + String region = dataObject.getString("region"); + return BLOCKED_COUNTRY_NAMES.contains(country) || BLOCKED_COUNTRY_NAMES.contains(region); + } + private static JSONObject normalizeIpNcGy(String provider, JSONObject jsonObject) { JSONObject countryObject = jsonObject.getJSONObject("country"); if (countryObject == null) { diff --git a/rc-auth/src/test/java/com/red/circle/auth/common/LoginAccessValidationServiceTest.java b/rc-auth/src/test/java/com/red/circle/auth/common/LoginAccessValidationServiceTest.java index 04b74f11..6f5dadf0 100644 --- a/rc-auth/src/test/java/com/red/circle/auth/common/LoginAccessValidationServiceTest.java +++ b/rc-auth/src/test/java/com/red/circle/auth/common/LoginAccessValidationServiceTest.java @@ -70,11 +70,39 @@ public class LoginAccessValidationServiceTest { } @Test - public void allowChinaSpecialRegions() { + public void blockHongKongRegion() { JSONObject data = JSON.parseObject(""" {"country_id":"CN","country":"中国","region":"香港"} """); assertFalse(LoginAccessValidationService.isMainlandChina(data)); + assertTrue(LoginAccessValidationService.isBlockedIpRegion(data)); + } + + @Test + public void blockMacauCountryCode() { + JSONObject data = JSON.parseObject(""" + {"country_id":"MO","country":"Macao","region":""} + """); + + assertTrue(LoginAccessValidationService.isBlockedIpRegion(data)); + } + + @Test + public void blockSingaporeCountryCode() { + JSONObject data = JSON.parseObject(""" + {"country_id":"SG","country":"Singapore","region":""} + """); + + assertTrue(LoginAccessValidationService.isBlockedIpRegion(data)); + } + + @Test + public void allowTaiwanRegion() { + JSONObject data = JSON.parseObject(""" + {"country_id":"CN","country":"中国","region":"台湾"} + """); + + assertFalse(LoginAccessValidationService.isBlockedIpRegion(data)); } } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/user/LoginLoggerListener.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/user/LoginLoggerListener.java index 4ced613e..4a1edc9b 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/user/LoginLoggerListener.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/user/LoginLoggerListener.java @@ -336,8 +336,10 @@ public class LoginLoggerListener implements MessageListener { return LoginBlockResult.notBlocked(); } List reasons = new ArrayList<>(); - if (IpCountryUtils.isMainlandChina(ipGeoData)) { - reasons.add("中国大陆IP"); + if (IpCountryUtils.isBlockedIpRegion(ipGeoData)) { + reasons.add(IpCountryUtils.isMainlandChina(ipGeoData) + ? "中国大陆IP" + : "受限IP地区:" + blockedRegionName(ipGeoData)); } if (Objects.equals("Asia/Shanghai", event.getZoneId())) { reasons.add("中国时区"); @@ -347,6 +349,22 @@ public class LoginLoggerListener implements MessageListener { : new LoginBlockResult(true, String.join(",", reasons)); } + private String blockedRegionName(IpCountryUtils.IpGeoData ipGeoData) { + if (Objects.isNull(ipGeoData) || ipGeoData.isEmpty()) { + return ""; + } + if (StringUtils.isNotBlank(ipGeoData.region())) { + return ipGeoData.region(); + } + if (StringUtils.isNotBlank(ipGeoData.countryName())) { + return ipGeoData.countryName(); + } + if (StringUtils.isNotBlank(ipGeoData.countryCode())) { + return ipGeoData.countryCode(); + } + return ipGeoData.region(); + } + private boolean isLoginWhiteAccount(LoginLoggerEvent event, UserProfile userProfile) { if (Objects.isNull(userProfile) || StringUtils.isBlank(userProfile.getAccount())) { return false; diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/utils/IpCountryUtils.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/utils/IpCountryUtils.java index c11100f1..7d58dea3 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/utils/IpCountryUtils.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/utils/IpCountryUtils.java @@ -31,6 +31,12 @@ public class IpCountryUtils { private static final List ALLOWED_CHINA_REGIONS = List.of( "香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan" ); + private static final List BLOCKED_COUNTRY_CODES = List.of( + "HK", "MO", "SG" + ); + private static final List BLOCKED_COUNTRY_NAMES = List.of( + "香港", "澳门", "澳門", "Hong Kong", "Macau", "Macao", "新加坡", "Singapore" + ); private static final List IP_GEO_PROVIDERS = List.of( new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"), new IpGeoProvider("freeipapi", "https://freeipapi.com/api/json/%s"), @@ -95,6 +101,10 @@ public class IpCountryUtils { return isMainlandChina(getGeoData(ip)); } + public static boolean isBlockedIpRegion(IpGeoData data) { + return isMainlandChina(data) || isBlockedCountryOrRegion(data); + } + public static boolean isMainlandChina(IpGeoData data) { if (data == null || data.isEmpty()) { return false; @@ -108,6 +118,18 @@ public class IpCountryUtils { return StringUtils.isBlank(data.region()) || !ALLOWED_CHINA_REGIONS.contains(data.region()); } + private static boolean isBlockedCountryOrRegion(IpGeoData data) { + if (data == null || data.isEmpty()) { + return false; + } + if (StringUtils.isNotBlank(data.countryCode()) + && BLOCKED_COUNTRY_CODES.contains(data.countryCode().trim().toUpperCase(Locale.ROOT))) { + return true; + } + return BLOCKED_COUNTRY_NAMES.contains(data.countryName()) + || BLOCKED_COUNTRY_NAMES.contains(data.region()); + } + private IpGeoData requestIpGeoData(CloseableHttpClient httpClient, IpGeoProvider provider, String ip) { String requestUrl = provider.buildUrl(ip); HttpGet httpGet = new HttpGet(requestUrl); diff --git a/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/utils/IpCountryUtilsTest.java b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/utils/IpCountryUtilsTest.java index 50f83903..2272368a 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/utils/IpCountryUtilsTest.java +++ b/rc-service/rc-service-other/other-infrastructure/src/test/java/com/red/circle/other/infra/utils/IpCountryUtilsTest.java @@ -69,9 +69,31 @@ public class IpCountryUtilsTest { } @Test - public void allowChinaSpecialRegions() { + public void blockHongKongRegion() { IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("CN", "中国", "香港", "test"); assertFalse(IpCountryUtils.isMainlandChina(data)); + assertTrue(IpCountryUtils.isBlockedIpRegion(data)); + } + + @Test + public void blockMacauCountryCode() { + IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("MO", "Macao", "", "test"); + + assertTrue(IpCountryUtils.isBlockedIpRegion(data)); + } + + @Test + public void blockSingaporeCountryCode() { + IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("SG", "Singapore", "", "test"); + + assertTrue(IpCountryUtils.isBlockedIpRegion(data)); + } + + @Test + public void allowTaiwanRegion() { + IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("CN", "中国", "台湾", "test"); + + assertFalse(IpCountryUtils.isBlockedIpRegion(data)); } }