在实际的业务中,涉及到攻防数据的演示,但是基础的数据只有攻击的IP,如何在地图上展示攻击的来源?
地图飞线或者坐标点的展示都是通过经纬度进行设置的,如果拿不到对应的经纬度则无法对地图攻击来源进行演示。为此查找方案,可以通过IP对经纬度的转换来实现攻击的展现(坐标点存在误差,非精确经纬度)。

通过输入一个IP地址,解析并获取信息,比如国家、国家代码、省份、省份代码、城市、邮政编码、经纬度等等信息

在线IP获取地区

image.png

二、springboot项目整合及使用

1、添加依赖

  1. <dependency>
  2. <groupId>com.maxmind.geoip2</groupId>
  3. <artifactId>geoip2</artifactId>
  4. <version>2.13.1</version>
  5. </dependency>

2、实现工具类

  1. package com.qingfeng.common.controller;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.net.InetAddress;
  5. import javax.servlet.http.HttpServletRequest;
  6. import com.maxmind.geoip2.DatabaseReader;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. /**
  11. * @ProjectName IpGeoUtils
  12. * @author Administrator
  13. * @version 1.0.0
  14. * @Description 获取客户端IP地址
  15. * @createTime 2021/6/3 14:29
  16. */
  17. public class IpGeoUtils {
  18. private static Logger logger = LoggerFactory.getLogger(IpGeoUtils.class);
  19. /**
  20. * 获取客户端IP地址
  21. *
  22. * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
  23. * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
  24. */
  25. public static String getIP(HttpServletRequest request) {
  26. String ip = null;
  27. try {
  28. ip = request.getHeader("x-forwarded-for");
  29. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  30. ip = request.getHeader("Proxy-Client-IP");
  31. }
  32. if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  33. ip = request.getHeader("WL-Proxy-Client-IP");
  34. }
  35. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  36. ip = request.getHeader("HTTP_CLIENT_IP");
  37. }
  38. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  39. ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  40. }
  41. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  42. ip = request.getRemoteAddr();
  43. }
  44. } catch (Exception e) {
  45. logger.error("IPUtils ERROR ", e);
  46. }
  47. return ip;
  48. }
  49. /**
  50. *
  51. * @description: 获得国家
  52. * @param reader
  53. * @param ip
  54. * @return
  55. * @throws Exception
  56. */
  57. public static String getCountry(DatabaseReader reader, String ip) throws Exception {
  58. return reader.city(InetAddress.getByName(ip)).getCountry().getNames().get("zh-CN");
  59. }
  60. /**
  61. *
  62. * @description: 获得省份
  63. * @param reader
  64. * @param ip
  65. * @return
  66. * @throws Exception
  67. */
  68. public static String getProvince(DatabaseReader reader, String ip) throws Exception {
  69. return reader.city(InetAddress.getByName(ip)).getMostSpecificSubdivision().getNames().get("zh-CN");
  70. }
  71. /**
  72. *
  73. * @description: 获得城市
  74. * @param reader
  75. * @param ip
  76. * @return
  77. * @throws Exception
  78. */
  79. public static String getCity(DatabaseReader reader, String ip) throws Exception {
  80. return reader.city(InetAddress.getByName(ip)).getCity().getNames().get("zh-CN");
  81. }
  82. /**
  83. *
  84. * @description: 获得经度
  85. * @param reader
  86. * @param ip
  87. * @return
  88. * @throws Exception
  89. */
  90. public static Double getLongitude(DatabaseReader reader, String ip) throws Exception {
  91. // return reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
  92. double data = 0;
  93. try {
  94. data = reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
  95. }catch (Exception e){
  96. }
  97. return data;
  98. }
  99. /**
  100. *
  101. * @description: 获得纬度
  102. * @param reader
  103. * @param ip
  104. * @return
  105. * @throws Exception
  106. */
  107. public static Double getLatitude(DatabaseReader reader, String ip){
  108. double data = 0;
  109. try {
  110. data = reader.city(InetAddress.getByName(ip)).getLocation().getLatitude();
  111. }catch (Exception e){
  112. }
  113. return data;
  114. }
  115. public static void main(String[] args) throws Exception {
  116. // String path = req.getSession().getServletContext().getRealPath("/WEB-INF/classes/GeoLite2-City.mmdb");
  117. String path = "D:/java/GeoLite2-City/GeoLite2-City.mmdb";
  118. // 创建 GeoLite2 数据库
  119. File database = new File(path);
  120. // 读取数据库内容
  121. DatabaseReader reader = new DatabaseReader.Builder(database).build();
  122. // 访问IP
  123. String ip = "28.16.2.122";
  124. String site = IpGeoUtils.getCountry(reader, ip) + "-" + IpGeoUtils.getLongitude(reader, ip)+ "-" + IpGeoUtils.getLatitude(reader, ip);
  125. System.out.println(site);
  126. Double lon = IpGeoUtils.getLongitude(reader,ip);
  127. double lat = IpGeoUtils.getLatitude(reader,ip);
  128. System.out.println("Lon:"+lon+"---Lat:"+lat);
  129. }
  130. }

3、实现及调用

  1. //引入GeoLite2
  2. String path = "D:/java/GeoLite2-City.mmdb";
  3. // 创建 GeoLite2 数据库
  4. File database = new File(path);
  5. // 读取数据库内容
  6. DatabaseReader reader = new DatabaseReader.Builder(database).build();
  7. Double lon = IpGeoUtils.getLongitude(reader,ip);
  8. double lat = IpGeoUtils.getLatitude(reader,ip);
  9. System.out.println("Lon:"+lon+"---Lat:"+lat);

4、完整案例代码

因为实际业务需要查询出攻击所在的IP地址,根据IP地址获取经纬度-更新信息,将获取的经纬度更新到库中。
为了快速的实现数据的获取及更新,直接使用demo连接mysql数据库进行操作,完整代码如下:

  1. package com.qingfeng.example.controller;
  2. import com.maxmind.geoip2.DatabaseReader;
  3. import com.qingfeng.util.IpGeoUtils;
  4. import com.qingfeng.util.PageData;
  5. import com.qingfeng.util.Verify;
  6. import com.qingfeng.util.sqlutil.DBMysqlUtil;
  7. import org.apache.commons.lang3.StringUtils;
  8. import java.io.File;
  9. import java.sql.ResultSet;
  10. import java.sql.ResultSetMetaData;
  11. import java.sql.SQLException;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. /**
  15. * @author Administrator
  16. * @version 1.0.0
  17. * @ProjectName qingfeng
  18. * @Description TODO
  19. * @createTime 20210603 14:35:00
  20. */
  21. public class IpToGeo {
  22. /**
  23. * @title 根据ip获取经纬度
  24. * @description TODO
  25. * @author Administrator
  26. * @updateTime 2021/6/3 14:36
  27. */
  28. public static void main(String[] args) throws Exception {
  29. String path = "D:/java/GeoLite2-City.mmdb";
  30. // 创建 GeoLite2 数据库
  31. File database = new File(path);
  32. // 读取数据库内容
  33. DatabaseReader reader = new DatabaseReader.Builder(database).build();
  34. String dbUrl = "jdbc:mysql://localhost:3306/perception?serverTimezone=UTC&autoReconnect=true&useUnicode=true&characterEncoding=utf8";
  35. DBMysqlUtil db = new DBMysqlUtil(dbUrl,"root","Root@123");
  36. db.getConnection();
  37. String querySql = "select id,attack_ip from egov_data where attack_lon is null and attack_ip not like '%192.0.0%' order by id asc";
  38. ResultSet rs = db.select(querySql);
  39. List<PageData> list = new ArrayList<PageData>();
  40. while (rs.next()) {
  41. PageData p = new PageData();
  42. String id = rs.getString("id");
  43. String attack_ip = rs.getString("attack_ip");
  44. System.out.println("id:"+id+"---IP:"+attack_ip);
  45. String ip = "";
  46. if(attack_ip.contains("(")){
  47. ip = attack_ip.substring(0,attack_ip.indexOf("("));
  48. }
  49. System.out.println("IP:"+ip);
  50. if(Verify.verifyIsNotNull(ip)){
  51. Double lon = IpGeoUtils.getLongitude(reader,ip);
  52. double lat = IpGeoUtils.getLatitude(reader,ip);
  53. System.out.println("Lon:"+lon+"---Lat:"+lat);
  54. p.put("id",id);
  55. p.put("lon",lon);
  56. p.put("lat",lat);
  57. list.add(p);
  58. }
  59. }
  60. for (PageData p:list) {
  61. //执行更新
  62. String updateSql = "update egov_data set attack_lon='"+p.get("lon")+"',attack_lat='"+p.get("lat")+"' where id="+p.get("id");
  63. db.executeupdate(updateSql);
  64. }
  65. }
  66. }