Pre Merge pull request !651 from wuzhiming/ipv6-support
This commit is contained in:
commit
1a1af540dc
8
pom.xml
8
pom.xml
@ -39,7 +39,7 @@
|
||||
<justauth.version>1.16.7</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
|
||||
<geoip2.version>4.2.1</geoip2.version>
|
||||
<!-- OSS 配置 -->
|
||||
<aws.sdk.version>2.28.22</aws.sdk.version>
|
||||
<aws.crt.version>0.31.3</aws.crt.version>
|
||||
@ -320,6 +320,12 @@
|
||||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.maxmind.geoip2</groupId>
|
||||
<artifactId>geoip2</artifactId>
|
||||
<version>${geoip2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
|
BIN
ruoyi-admin/src/main/resources/GeoLite2-City.mmdb
Normal file
BIN
ruoyi-admin/src/main/resources/GeoLite2-City.mmdb
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 MiB |
@ -94,6 +94,12 @@
|
||||
<artifactId>ip2region</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.maxmind.geoip2</groupId>
|
||||
<artifactId>geoip2</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,11 +1,13 @@
|
||||
package org.dromara.common.core.utils.ip;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* 获取地址类
|
||||
@ -17,17 +19,19 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class AddressUtils {
|
||||
|
||||
// 未知地址
|
||||
public static final String UNKNOWN = "XX XX";
|
||||
public static final String UNKNOWN = "未知";
|
||||
|
||||
public static String getRealAddressByIP(String ip) {
|
||||
if (StringUtils.isBlank(ip)) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
// 内网不查询
|
||||
ip = StringUtils.contains(ip, "0:0:0:0:0:0:0:1") ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
||||
if (NetUtil.isInnerIP(ip)) {
|
||||
return "内网IP";
|
||||
ip = HtmlUtil.cleanHtmlTag(ip).trim();
|
||||
try {
|
||||
InetAddress ipAddress = InetAddress.getByName(ip);
|
||||
return RegionUtils.getCityInfo(ipAddress);
|
||||
} catch (UnknownHostException e) {
|
||||
log.error("IP地址离线获取城市异常 {}", ip);
|
||||
return UNKNOWN;
|
||||
}
|
||||
return RegionUtils.getCityInfo(ip);
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,26 @@ package org.dromara.common.core.utils.ip;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.resource.ClassPathResource;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import com.maxmind.geoip2.exception.GeoIp2Exception;
|
||||
import com.maxmind.geoip2.model.CityResponse;
|
||||
import com.maxmind.geoip2.record.City;
|
||||
import com.maxmind.geoip2.record.Country;
|
||||
import com.maxmind.geoip2.record.Subdivision;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.file.FileUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.lionsoul.ip2region.xdb.Searcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 根据ip地址定位工具类,离线方式
|
||||
* 参考地址:<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">集成 ip2region 实现离线IP地址定位库</a>
|
||||
*
|
||||
* @author lishuyan
|
||||
*/
|
||||
@ -20,19 +30,22 @@ import java.io.File;
|
||||
public class RegionUtils {
|
||||
|
||||
private static final Searcher SEARCHER;
|
||||
private static final DatabaseReader reader;
|
||||
private static final String locale;
|
||||
|
||||
static {
|
||||
String fileName = "/ip2region.xdb";
|
||||
File existFile = FileUtils.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
|
||||
if (!FileUtils.exist(existFile)) {
|
||||
ClassPathResource fileStream = new ClassPathResource(fileName);
|
||||
//ipv4初始化
|
||||
String fileName4 = "/ip2region.xdb";
|
||||
File existFile4 = FileUtils.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName4);
|
||||
if (!FileUtils.exist(existFile4)) {
|
||||
ClassPathResource fileStream = new ClassPathResource(fileName4);
|
||||
if (ObjectUtil.isEmpty(fileStream.getStream())) {
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:IP地址库数据不存在!");
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:IPv4地址库数据不存在!");
|
||||
}
|
||||
FileUtils.writeFromStream(fileStream.getStream(), existFile);
|
||||
FileUtils.writeFromStream(fileStream.getStream(), existFile4);
|
||||
}
|
||||
|
||||
String dbPath = existFile.getPath();
|
||||
String dbPath = existFile4.getPath();
|
||||
|
||||
// 1、从 dbPath 加载整个 xdb 到内存。
|
||||
byte[] cBuff;
|
||||
@ -47,21 +60,69 @@ public class RegionUtils {
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:" + e.getMessage());
|
||||
}
|
||||
|
||||
//ipv6初始化
|
||||
//文件来源 https://download.db-ip.com/free/dbip-city-lite-2025-03.mmdb.gz (db-ip官方免费版本,中文支持不好)
|
||||
//文件来源 https://gitee.com/allen0769/GeoLite.mmdb.git
|
||||
String fileName6 = "/GeoLite2-City.mmdb";
|
||||
File existFile6 = FileUtils.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName6);
|
||||
if (!FileUtils.exist(existFile6)) {
|
||||
ClassPathResource fileStream = new ClassPathResource(fileName6);
|
||||
if (ObjectUtil.isEmpty(fileStream.getStream())) {
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:IP6地址库数据不存在!");
|
||||
}
|
||||
FileUtils.writeFromStream(fileStream.getStream(), existFile6);
|
||||
}
|
||||
try {
|
||||
reader = new DatabaseReader.Builder(existFile6).build();
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("RegionUtils初始化失败,原因:从GeoLite2-City.mmdb文件加载内容失败!" + e.getMessage());
|
||||
}
|
||||
locale = Locale.getDefault().toString().replace("_", "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IP地址离线获取城市
|
||||
*/
|
||||
public static String getCityInfo(String ip) {
|
||||
public static String getCityInfo(InetAddress ipAddress) {
|
||||
try {
|
||||
ip = ip.trim();
|
||||
// 3、执行查询
|
||||
String region = SEARCHER.search(ip);
|
||||
return region.replace("0|", "").replace("|0", "");
|
||||
if (ipAddress.isSiteLocalAddress() || ipAddress.isLinkLocalAddress() || ipAddress.isLoopbackAddress()) {
|
||||
return "内网IP";
|
||||
}
|
||||
if (ipAddress instanceof Inet4Address) {
|
||||
return getCityInfoIpv4(ipAddress);
|
||||
} else if (ipAddress instanceof Inet6Address) {
|
||||
return getCityInfoIpv6(ipAddress);
|
||||
} else {
|
||||
return "未知";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("IP地址离线获取城市异常 {}", ip);
|
||||
log.error("IP地址 {} 离线获取城市异常 {}", ipAddress.getAddress(), e.getMessage());
|
||||
return "未知";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IPV4地址离线获取城市
|
||||
*/
|
||||
private static String getCityInfoIpv4(InetAddress ipAddress) throws Exception {
|
||||
String region = SEARCHER.search(ipAddress.getHostAddress());
|
||||
//中国|江苏省|南京市|电信
|
||||
return region.replace("0|", "").replace("|0", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据IPV6地址离线获取城市
|
||||
*/
|
||||
private static String getCityInfoIpv6(InetAddress ipAddress) throws IOException, GeoIp2Exception {
|
||||
CityResponse cityResponse = reader.city(ipAddress);
|
||||
Country country = cityResponse.getCountry();
|
||||
Subdivision subdivision = cityResponse.getMostSpecificSubdivision();
|
||||
City city = cityResponse.getCity();
|
||||
String countryStr = country.getNames().get(locale) != null ? country.getNames().get(locale) : country.getName();
|
||||
String subdivisionStr = subdivision.getNames().get(locale) != null ? subdivision.getNames().get(locale) : subdivision.getName();
|
||||
String cityStr = city.getNames().get(locale) != null ? city.getNames().get(locale) : city.getName();
|
||||
return countryStr + "|" + subdivisionStr + "|" + cityStr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,10 +39,12 @@ http {
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80 ipv6only=on;
|
||||
server_name localhost;
|
||||
|
||||
# https配置参考 start
|
||||
#listen 443 ssl;
|
||||
#listen [::]:443 ssl ipv6only=on;
|
||||
|
||||
# 证书直接存放 /docker/nginx/cert/ 目录下即可 更改证书名称即可 无需更改证书路径
|
||||
#ssl on;
|
||||
|
Loading…
x
Reference in New Issue
Block a user