IPUtil.java 7.71 KB
package vion.utils.ip;

import com.maxmind.db.CHMCache;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.record.AbstractNamedRecord;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author vion
 * @date 2024/8/29
 */
@Component
@Slf4j
public class IPUtil {

    private static String asnPath;
    private static String cityPath;

    @Value("${geo.asn.path}")
    public void setAsnPath(String asnPath) {
        IPUtil.asnPath = asnPath;
    }

    @Value("${geo.city.path}")
    public void setCityPath(String cityPath) {
        IPUtil.cityPath = cityPath;
    }

    public static Map<Integer, String> asnMap = new HashMap<>() {{
        put(9812, "东方有线");
        put(9389, "中国长城");
        put(17962, "天威视讯");
        put(17429, "歌华有线");
        put(7497, "科技网");
        put(24139, "华数");
        put(9801, "中关村");
        put(4538, "教育网");
        put(24151, "CNNIC");
        // 添加中国移动ASN映射
        put(38019, "中国移动");
        put(139080, "中国移动");
        put(9808, "中国移动");
        put(24400, "中国移动");
        put(134810, "中国移动");
        put(24547, "中国移动");
        put(56040, "中国移动");
        put(56041, "中国移动");
        put(56042, "中国移动");
        put(56044, "中国移动");
        put(132525, "中国移动");
        put(56046, "中国移动");
        put(56047, "中国移动");
        put(56048, "中国移动");
        put(59257, "中国移动");
        put(24444, "中国移动");
        put(24445, "中国移动");
        put(137872, "中国移动");
        put(9231, "中国移动");
        put(58453, "中国移动");
        // 添加中国电信ASN映射
        put(4134, "中国电信");
        put(4812, "中国电信");
        put(23724, "中国电信");
        put(136188, "中国电信");
        put(137693, "中国电信");
        put(17638, "中国电信");
        put(140553, "中国电信");
        put(4847, "中国电信");
        put(140061, "中国电信");
        put(136195, "中国电信");
        put(17799, "中国电信");
        put(139018, "中国电信");
        put(133776, "中国电信");
        put(58772, "中国电信");
        put(146966, "中国电信");
        put(63527, "中国电信");
        put(58539, "中国电信");
        put(58540, "中国电信");
        put(141998, "中国电信");
        put(138169, "中国电信");
        put(139203, "中国电信");
        put(58563, "中国电信");
        put(137690, "中国电信");
        put(63838, "中国电信");
        put(137694, "中国电信");
        put(137698, "中国电信");
        put(136167, "中国电信");
        put(148969, "中国电信");
        put(134764, "中国电信");
        put(134770, "中国电信");
        put(148981, "中国电信");
        put(134774, "中国电信");
        put(136190, "中国电信");
        put(140647, "中国电信");
        put(132225, "中国电信");
        put(140485, "中国电信");
        put(4811, "中国电信");
        put(131285, "中国电信");
        put(137689, "中国电信");
        put(137692, "中国电信");
        put(140636, "中国电信");
        put(140638, "中国电信");
        put(140345, "中国电信");
        put(38283, "中国电信");
        put(140292, "中国电信");
        put(140903, "中国电信");
        put(17897, "中国电信");
        put(134762, "中国电信");
        put(139019, "中国电信");
        put(141739, "中国电信");
        put(141771, "中国电信");
        put(134419, "中国电信");
        put(140276, "中国电信");
        put(58542, "中国电信");
        put(140278, "中国电信");
        put(139767, "中国电信");
        put(137688, "中国电信");
        put(137691, "中国电信");
        put(4809, "中国电信");
        put(58466, "中国电信");
        put(137687, "中国电信");
        put(134756, "中国电信");
        put(134760, "中国电信");
        put(133774, "中国电信");
        put(133775, "中国电信");
        put(4816, "中国电信");
        put(134768, "中国电信");
        put(58461, "中国电信");
        put(58519, "中国电信");
        put(58520, "中国电信");
        put(131325, "中国电信");
        // 添加中国联通ASN映射
        put(4837, "中国联通");
        put(4808, "中国联通");
        put(134542, "中国联通");
        put(134543, "中国联通");
        put(10099, "中国联通");
        put(140979, "中国联通");
        put(138421, "中国联通");
        put(17621, "中国联通");
        put(17622, "中国联通");
        put(17816, "中国联通");
        put(140726, "中国联通");
        put(17623, "中国联通");
        put(136958, "中国联通");
        put(9929, "中国联通");
        put(58519, "中国联通");
        put(140716, "中国联通");
        put(4847, "中国联通");
        put(136959, "中国联通");
        put(135061, "中国联通");
        put(139007, "中国联通");
        // 添加其他ASN映射
        put(59019, "金山云");
        put(135377, "优刻云");
        put(45062, "网易云");
        put(137718, "火山引擎");
        put(37963, "阿里云");
        put(45102, "阿里云国际");
        put(45090, "腾讯云");
        put(132203, "腾讯云国际");
        put(55967, "百度云");
        put(38365, "百度云");
        put(58519, "华为云");
        put(55990, "华为云");
        put(136907, "华为云");
        put(4609, "澳門電訊");
        put(134773, "珠江宽频");
        put(1659, "台湾教育网");
        put(8075, "微软云");
        put(17421, "中华电信");
        put(3462, "HiNet");
        put(13335, "Cloudflare");
        put(55960, "亚马逊云");
        put(14618, "亚马逊云");
        put(16509, "亚马逊云");
        put(15169, "谷歌云");
        put(396982, "谷歌云");
        put(36492, "谷歌云");
    }};

    public static String getIp(String ip) {
        var cityDB = FileUtil.file(cityPath);
        var asnDB = FileUtil.file(asnPath);
        try (DatabaseReader cityReader = new DatabaseReader.Builder(cityDB)
                .withCache(new CHMCache())
                .locales(List.of("zh-CN")).build();
             DatabaseReader asnReader = new DatabaseReader.Builder(asnDB)
                     .withCache(new CHMCache())
                     .locales(List.of("zh-CN")).build()) {
            InetAddress address = InetAddress.getByName(ip);
            var asn = asnReader.asn(address);
            var asnNum = asn.getAutonomousSystemNumber();
            var asnOrg = asn.getAutonomousSystemOrganization();

            var city = cityReader.city(address);
            var cityName = city.getCity().getName();
            var province = city.getSubdivisions().stream().map(AbstractNamedRecord::getName).collect(Collectors.joining(","));
            var country = cityReader.country(address);
            var countryName = country.getCountry().getName();
            var asnStr = asnMap.getOrDefault(asnNum.intValue(), asnOrg);
            return StrUtil.format("Country:{}, Province:{}, City:{}, ASN:{}", countryName, province, cityName, asnStr);
        } catch (Exception e) {
            log.error("获取IP归属地失败:[{}],error:{}", ip, e.getMessage());
        }
        return StrUtil.format("Country:{}, Province:{}, City:{}, ASN:{}", "Unknown", "Unknown", "Unknown", "Unknown");
    }

}