在实际的业务中,涉及到攻防数据的演示,但是基础的数据只有攻击的IP,如何在地图上展示攻击的来源?
地图飞线或者坐标点的展示都是通过经纬度进行设置的,如果拿不到对应的经纬度则无法对地图攻击来源进行演示。为此查找方案,可以通过IP对经纬度的转换来实现攻击的展现(坐标点存在误差,非精确经纬度)。
通过输入一个IP地址,解析并获取信息,比如国家、国家代码、省份、省份代码、城市、邮政编码、经纬度等等信息
在线IP获取地区
- ip-api.com
一、GeoLite2 介绍
通过GeoLite2,Java根据IP获得城市、经纬度。
1179px下载地址:https://www.maxmind.com/en/accounts/561549/geoip/downloads
因为我需要获取城市信息,所以选择第三个,压缩包大概30MB,解压后里面的 mmdb 有60MB
二、springboot项目整合及使用
1、添加依赖
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.13.1</version>
</dependency>
2、实现工具类
package com.qingfeng.common.controller;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import javax.servlet.http.HttpServletRequest;
import com.maxmind.geoip2.DatabaseReader;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @ProjectName IpGeoUtils
* @author Administrator
* @version 1.0.0
* @Description 获取客户端IP地址
* @createTime 2021/6/3 14:29
*/
public class IpGeoUtils {
private static Logger logger = LoggerFactory.getLogger(IpGeoUtils.class);
/**
* 获取客户端IP地址
*
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIP(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
return ip;
}
/**
*
* @description: 获得国家
* @param reader
* @param ip
* @return
* @throws Exception
*/
public static String getCountry(DatabaseReader reader, String ip) throws Exception {
return reader.city(InetAddress.getByName(ip)).getCountry().getNames().get("zh-CN");
}
/**
*
* @description: 获得省份
* @param reader
* @param ip
* @return
* @throws Exception
*/
public static String getProvince(DatabaseReader reader, String ip) throws Exception {
return reader.city(InetAddress.getByName(ip)).getMostSpecificSubdivision().getNames().get("zh-CN");
}
/**
*
* @description: 获得城市
* @param reader
* @param ip
* @return
* @throws Exception
*/
public static String getCity(DatabaseReader reader, String ip) throws Exception {
return reader.city(InetAddress.getByName(ip)).getCity().getNames().get("zh-CN");
}
/**
*
* @description: 获得经度
* @param reader
* @param ip
* @return
* @throws Exception
*/
public static Double getLongitude(DatabaseReader reader, String ip) throws Exception {
// return reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
double data = 0;
try {
data = reader.city(InetAddress.getByName(ip)).getLocation().getLongitude();
}catch (Exception e){
}
return data;
}
/**
*
* @description: 获得纬度
* @param reader
* @param ip
* @return
* @throws Exception
*/
public static Double getLatitude(DatabaseReader reader, String ip){
double data = 0;
try {
data = reader.city(InetAddress.getByName(ip)).getLocation().getLatitude();
}catch (Exception e){
}
return data;
}
public static void main(String[] args) throws Exception {
// String path = req.getSession().getServletContext().getRealPath("/WEB-INF/classes/GeoLite2-City.mmdb");
String path = "D:/java/GeoLite2-City/GeoLite2-City.mmdb";
// 创建 GeoLite2 数据库
File database = new File(path);
// 读取数据库内容
DatabaseReader reader = new DatabaseReader.Builder(database).build();
// 访问IP
String ip = "28.16.2.122";
String site = IpGeoUtils.getCountry(reader, ip) + "-" + IpGeoUtils.getLongitude(reader, ip)+ "-" + IpGeoUtils.getLatitude(reader, ip);
System.out.println(site);
Double lon = IpGeoUtils.getLongitude(reader,ip);
double lat = IpGeoUtils.getLatitude(reader,ip);
System.out.println("Lon:"+lon+"---Lat:"+lat);
}
}
3、实现及调用
//引入GeoLite2
String path = "D:/java/GeoLite2-City.mmdb";
// 创建 GeoLite2 数据库
File database = new File(path);
// 读取数据库内容
DatabaseReader reader = new DatabaseReader.Builder(database).build();
Double lon = IpGeoUtils.getLongitude(reader,ip);
double lat = IpGeoUtils.getLatitude(reader,ip);
System.out.println("Lon:"+lon+"---Lat:"+lat);
4、完整案例代码
因为实际业务需要查询出攻击所在的IP地址,根据IP地址获取经纬度-更新信息,将获取的经纬度更新到库中。
为了快速的实现数据的获取及更新,直接使用demo连接mysql数据库进行操作,完整代码如下:
package com.qingfeng.example.controller;
import com.maxmind.geoip2.DatabaseReader;
import com.qingfeng.util.IpGeoUtils;
import com.qingfeng.util.PageData;
import com.qingfeng.util.Verify;
import com.qingfeng.util.sqlutil.DBMysqlUtil;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Administrator
* @version 1.0.0
* @ProjectName qingfeng
* @Description TODO
* @createTime 2021年06月03日 14:35:00
*/
public class IpToGeo {
/**
* @title 根据ip获取经纬度
* @description TODO
* @author Administrator
* @updateTime 2021/6/3 14:36
*/
public static void main(String[] args) throws Exception {
String path = "D:/java/GeoLite2-City.mmdb";
// 创建 GeoLite2 数据库
File database = new File(path);
// 读取数据库内容
DatabaseReader reader = new DatabaseReader.Builder(database).build();
String dbUrl = "jdbc:mysql://localhost:3306/perception?serverTimezone=UTC&autoReconnect=true&useUnicode=true&characterEncoding=utf8";
DBMysqlUtil db = new DBMysqlUtil(dbUrl,"root","Root@123");
db.getConnection();
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";
ResultSet rs = db.select(querySql);
List<PageData> list = new ArrayList<PageData>();
while (rs.next()) {
PageData p = new PageData();
String id = rs.getString("id");
String attack_ip = rs.getString("attack_ip");
System.out.println("id:"+id+"---IP:"+attack_ip);
String ip = "";
if(attack_ip.contains("(")){
ip = attack_ip.substring(0,attack_ip.indexOf("("));
}
System.out.println("IP:"+ip);
if(Verify.verifyIsNotNull(ip)){
Double lon = IpGeoUtils.getLongitude(reader,ip);
double lat = IpGeoUtils.getLatitude(reader,ip);
System.out.println("Lon:"+lon+"---Lat:"+lat);
p.put("id",id);
p.put("lon",lon);
p.put("lat",lat);
list.add(p);
}
}
for (PageData p:list) {
//执行更新
String updateSql = "update egov_data set attack_lon='"+p.get("lon")+"',attack_lat='"+p.get("lat")+"' where id="+p.get("id");
db.executeupdate(updateSql);
}
}
}