Java-通过IP获取真实地址

news/2024/5/19 0:27:58/文章来源:https://blog.csdn.net/xhmico/article/details/131673991

文章目录

    • 前言
    • 功能实现
    • 测试

前言

最近写了一个日志系统,需要通过访问的 IP 地址来获取真实的地址,并且存到数据库中,我也是在网上看了一些文章,遂即整理了一下供大家参考。


功能实现

这个是获取正确 IP 地址的方法,可以直接使用的。

/*** 获取 IP 地址*/public static String getIpAddress(ServerHttpRequest request) {HttpHeaders headers = request.getHeaders();String ip = headers.getFirst(ParameterConstants.X_FORWARDED_FOR);if (ip != null && ip.length() != 0 && !ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {// 多次反向代理后会有多个ip值,第一个ip才是真实ipif (ip.contains(",")) {ip = ip.split(",")[0];}}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = headers.getFirst(ParameterConstants.PROXY_CLIENT_IP);}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = headers.getFirst(ParameterConstants.WL_PROXY_CLIENT_IP);}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = headers.getFirst(ParameterConstants.HTTP_CLIENT_IP);}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = headers.getFirst(ParameterConstants.HTTP_X_FORWARDED_FOR);}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = headers.getFirst(ParameterConstants.X_REAL_IP);}if (ip == null || ip.length() == 0 || ParameterConstants.UNKNOWN.equalsIgnoreCase(ip)) {ip = Objects.requireNonNull(request.getRemoteAddress()).getAddress().getHostAddress();if (ip.equals(ParameterConstants.LOCAL_IP_V4) || ip.equals(ParameterConstants.LOCAL_IP_V6)) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();ip = inet.getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}}}return ip;}/*** 获取请求IP.* @return String ip*/public static String getIpAddress(HttpServletRequest request) {String ip = null;Enumeration<?> enu = request.getHeaderNames();while (enu.hasMoreElements()) {String name = (String) enu.nextElement();if (ParameterConstants.CDN_SRC_IP.equalsIgnoreCase(name)|| ParameterConstants.X_FORWARDED_FOR.equalsIgnoreCase(name)|| ParameterConstants.PROXY_CLIENT_IP.equalsIgnoreCase(name)|| ParameterConstants.WL_PROXY_CLIENT_IP.equalsIgnoreCase(name)|| ParameterConstants.X_REAL_IP.equalsIgnoreCase(name)) {ip = request.getHeader(name);}if (org.apache.commons.lang3.StringUtils.isNotBlank(ip)){break;}}if (StringUtils.isBlank(ip)){ip = request.getRemoteAddr();}if (ip.equals(ParameterConstants.LOCAL_IP_V4) || ip.equals(ParameterConstants.LOCAL_IP_V6)) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();ip = inet.getHostAddress();} catch (UnknownHostException e) {e.printStackTrace();}}return ip;}

通过以上方法你可以获取到访问者的 IP 地址,只有获取到了 IP 地址,才能够拿到真实的地址

通过 IP 获取真实地址的方法有很多种,这里我只说两个:

  • 方式一:离线 IP 地址定位查询
  • 方式二:在线 IP 地址定位查询

方式一 我们需要在本地保存一个 IP 地址定位的文档,方式二就是通过 http 请求的方式访问一些可以查询 IP 地址所属地理位置的网址。

方式一就是查询比较快,但是有些地址可能查询不到,方式二就是基本上都能查到,但是要建立请求,会有点慢,所以将二者结合起来就行了。

导入依赖:

		<!-- 离线IP地址定位库 --><dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>1.7.2</version></dependency><!-- ali地域 --><dependency><groupId>com.maxmind.geoip2</groupId><artifactId>geoip2</artifactId><version>2.6.0</version></dependency>

添加离线 IP 地址库:

src/main/resources下新建 ip2region 复制文件 ip2region.db 到目录下

------------------ ip2region.db 资源下载 -----------------
链接:百度网盘
提取码:v7se
---------------------------------------------------------

添加工具类:

RegionUtil.java

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Objects;import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;/*** 根据ip离线查询地址** @author ruoyi*/
public class RegionUtil {private static final Logger log = LoggerFactory.getLogger(RegionUtil.class);private static final String JAVA_TEMP_DIR = "java.io.tmpdir";static DbConfig config = null;static DbSearcher searcher = null;// 初始化IP库static {try {// 因为jar无法读取文件,复制创建临时文件String dbPath = Objects.requireNonNull(RegionUtil.class.getResource("/ip2region/ip2region.db")).getPath();File file = new File(dbPath);if (!file.exists()) {String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR);dbPath = tmpDir + "ip2region.db";file = new File(dbPath);ClassPathResource cpr = new ClassPathResource("ip2region" + File.separator + "ip2region.db");InputStream resourceAsStream = cpr.getInputStream();FileUtils.copyInputStreamToFile(resourceAsStream, file);}config = new DbConfig();searcher = new DbSearcher(config, dbPath);log.info("bean [{}]", config);log.info("bean [{}]", searcher);} catch (Exception e) {log.error("init ip region error:{}", e.toString());}}/*** 解析IP** @param ip* @return*/public static String getRegion(String ip) {try {// dbif (searcher == null || StringUtils.isEmpty(ip)) {log.error("DbSearcher is null");return StringUtils.EMPTY;}long startTime = System.currentTimeMillis();// 查询算法Method method = searcher.getClass().getMethod("memorySearch", String.class);DataBlock dataBlock = null;if (!Util.isIpAddress(ip)) {log.warn("warning: Invalid ip address");}dataBlock = (DataBlock) method.invoke(searcher, ip);String result = dataBlock.getRegion();long endTime = System.currentTimeMillis();log.debug("region use time[{}] result[{}]", endTime - startTime, result);return result;} catch (Exception e) {log.error("error:{}", e.toString());}return StringUtils.EMPTY;}}

PureNetUtils.java

package com.mike.common.core.utils;import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;/*** 网络访问工具类*/
public class PureNetUtils {private static final Logger log = LoggerFactory.getLogger(PureNetUtils.class);/*** get方法直接调用post方法** @param url 网络地址* @return 返回网络数据*/public static String get(String url) {return post(url, null);}/*** 设定post方法获取网络资源,如果参数为null,实际上设定为get方法** @param url   网络地址* @param param 请求参数键值对* @return 返回读取数据*/public static String post(String url, Map<String, String> param) {HttpURLConnection conn = null;try {URL u = new URL(url);conn = (HttpURLConnection) u.openConnection();StringBuilder sb = null;if (param != null) {// 如果请求参数不为空sb = new StringBuilder();/** A URL connection can be used for input and/or output. Set the* DoOutput flag to true if you intend to use the URL connection* for output, false if not. The default is false.*/// 默认为false,post方法需要写入参数,设定trueconn.setDoOutput(true);// 设定post方法,默认getconn.setRequestMethod("POST");// 获得输出流OutputStream out = conn.getOutputStream();// 对输出流封装成高级输出流BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));// 将参数封装成键值对的形式for (Map.Entry<String, String> s : param.entrySet()) {sb.append(s.getKey()).append("=").append(s.getValue()).append("&");}// 将参数通过输出流写入writer.write(sb.deleteCharAt(sb.toString().length() - 1).toString());writer.close();// 一定要关闭,不然可能出现参数不全的错误sb = null;}conn.connect();// 建立连接sb = new StringBuilder();// 获取连接状态码int recode = conn.getResponseCode();BufferedReader reader = null;if (recode == 200) {// Returns an input stream that reads from this open connection// 从连接中获取输入流InputStream in = conn.getInputStream();// 对输入流进行封装reader = new BufferedReader(new InputStreamReader(in));String str = null;sb = new StringBuilder();// 从输入流中读取数据while ((str = reader.readLine()) != null) {sb.append(str).append(System.getProperty("line.separator"));}// 关闭输入流reader.close();if (sb.toString().length() == 0) {return null;}return sb.toString().substring(0,sb.toString().length() - System.getProperty("line.separator").length());}} catch (Exception e) {e.printStackTrace();return null;} finally {if (conn != null)// 关闭连接conn.disconnect();}return null;}/*** 获取 ip 所属地址** @param ip IP 地址* @return 所属地址*/public static String getAlibaba(String ip) {Map<String, String> map = new HashMap<>();map.put("ip", ip);map.put("accessKey", "alibaba-inc");String result = PureNetUtils.post("http://ip.taobao.com/outGetIpInfo", map);log.info("{} => POST: http://ip.taobao.com/outGetIpInfo || result: {}", ip, result);String address = null;if (StringUtils.isNotBlank(result)) {JSONObject jsonObject = JSONObject.parseObject(result);// 请求成功,解析响应数据if ("query success".equals(jsonObject.get("msg"))) {JSONObject dataMap = JSONObject.parseObject(jsonObject.getString("data"));String country = dataMap.getString("country");String region = dataMap.getString("region");String city = dataMap.getString("city");address = country + region + city;}}return address;}}

AddressUtils .java

import com.mike.common.core.utils.PureNetUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 获取地址类** @author ruoyi*/
public class AddressUtils {private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);// 未知地址public static final String UNKNOWN = "未知地址";public static String getRealAddress(String ip) {// 内网不查询if (internalIp(ip)) {return "内网IP";}try {String rspStr = RegionUtil.getRegion(ip);if (StringUtils.isNotEmpty(rspStr)) {String[] obj = rspStr.split("\\|");String region = obj[2];String city = obj[3];return String.format("%s%s", region, city);}} catch (Exception e) {log.error("获取地理位置异常 {}", e.toString());}// ali地域查询return PureNetUtils.getAlibaba(ip);}/* 判断是否是内网IP */public static boolean internalIp(String ipAddress) {boolean isInnerIp = false;long ipNum = getIpNum(ipAddress);/** 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类* 192.168.0.0-192.168.255.255 当然,还有127这个网段是环回地址*/long aBegin = getIpNum("10.0.0.0");long aEnd = getIpNum("10.255.255.255");long bBegin = getIpNum("172.16.0.0");long bEnd = getIpNum("172.31.255.255");long cBegin = getIpNum("192.168.0.0");long cEnd = getIpNum("192.168.255.255");isInnerIp = isInner(ipNum, aBegin, aEnd)|| isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd)|| ipAddress.equals("127.0.0.1");return isInnerIp;}/* 获取IP数 */private static long getIpNum(String ipAddress) {String[] ip = ipAddress.split("\\.");long a = Integer.parseInt(ip[0]);long b = Integer.parseInt(ip[1]);long c = Integer.parseInt(ip[2]);long d = Integer.parseInt(ip[3]);return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;}private static boolean isInner(long userIp, long begin, long end) {return (userIp >= begin) && (userIp <= end);}public static void main(String[] args) {String realAddress = getRealAddress("117.136.79.113");System.out.println("realAddress = " + realAddress);}
}String region = dataMap.getString("region");String city = dataMap.getString("city");address = country + region + city;}}return address;}/* 获取IP数 */private static long getIpNum(String ipAddress) {String[] ip = ipAddress.split("\\.");long a = Integer.parseInt(ip[0]);long b = Integer.parseInt(ip[1]);long c = Integer.parseInt(ip[2]);long d = Integer.parseInt(ip[3]);return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;}private static boolean isInner(long userIp, long begin, long end) {return (userIp >= begin) && (userIp <= end);}public static void main(String[] args) {String realAddress = getRealAddress("117.136.79.113");System.out.println("realAddress = " + realAddress);}
}

测试

运行 AddressUtils.javamain 方法测试

在这里插入图片描述


参考博客:
Java如何通过IP获得真实地址:https://blog.csdn.net/qq_39486119/article/details/107857455
集成ip2region实现离线IP地址定位:http://doc.ruoyi.vip/ruoyi/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_141320.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索基于300W-LP的3D人脸关键点检测

目录 前言一、&#xff13;D 关键点可视化二、使用步骤1.300W-LP转为YOLO数据格式2.修改数据入口3.开始训练 总结 前言 300WLP数据集提供来丰富的人脸线索&#xff0c;包括&#xff12;D或&#xff13;D的关键点信息&#xff0c;Head Angle和&#xff13;DMM的参数等&#xff…

Spring5学习笔记--详细一文通

Spring5学习笔记--详细一文通 1 Spring 框架概述1.1 Spring 5 简述1.2 Spring5入门案例1.2.1 Spring5下载1.1.2 打开 idea 工具&#xff0c;创建普通 Java 工程1.2.3 导入 Spring5 相关 jar 包1.2.4 创建普通类&#xff0c;在这个类创建普通方法1.2.5 创建 Spring 配置文件&…

分布式定时任务xxl-Job

目录 前言 项目介绍 1.源码目录介绍 2 “调度数据库”配置 3 架构设计 3.1 设计思想 5.3.3 架构图 实战 1.服务端部署 2.执行端配置 3.任务开发 3.1 基于方法注解任务 3.2 基于api任务 3.3 分片广播任务 4.任务执行 4.1 单任务执行 4.2 子任务执行 4.3 分片广…

一、rocketmq整体架构及nameServer源码分析

RocketMQ源码深入剖析 1 RocketMQ介绍 RocketMQ 是阿里巴巴集团基于高可用分布式集群技术&#xff0c;自主研发的云正式商用的专业消息中间件&#xff0c;既可为分布式应用系统提供异步解耦和削峰填谷的能力&#xff0c;同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠…

一次零基础靶机渗透细节全程记录

一、打靶总流程 1.确定目标&#xff1a; 在本靶场中&#xff0c;确定目标就是使用nmap进行ip扫描&#xff0c;确定ip即为目标&#xff0c;只是针对此靶场而言。其他实战中确定目标的方式包括nmap进行扫描&#xff0c;但不局限于这个nmap。 2.信息收集&#xff1a; 比如平常挖…

经典的网络安全技术

以我的理解&#xff0c;“黑客”大体上应该分为“正”、“邪”两类&#xff0c;正派黑客依靠自己掌握的知识帮助系统管理员找出系统中的漏洞并加以完善&#xff0c;而邪派黑客则是通过各种黑客技能对系统进行攻击、入侵或者做其他一些有害于网络的事情&#xff0c;因为邪派黑客…

RPC分布式网络通信框架(二)—— moduo网络解析

文章目录 一、框架通信原理二、框架初始化框架初始化 三、调用端&#xff08;客户端&#xff09;调用端框架调用端主程序 四、提供端&#xff08;服务器&#xff09;提供端主程序提供端框架NotifyService方法Run方法muduo库的优点网络代码RpcProvider::OnConnection业务代码Rpc…

win11利用start11实现全屏菜单,磁贴配置

Win11磁贴配置 最近电脑还是升级到 win11 了。我之前采用的美化方案是桌面上的图标全部移到 win10 开始菜单里的全屏菜单上&#xff0c;用磁贴贴一排。每次要访问文件的时候都去开始菜单里找&#xff0c;而不是放在桌面上&#xff0c;这样桌面也可以空出来欣赏壁纸。参考配置链…

springboot+MySQL大学生体质测试管理系统

功能需求分析的任务是通过详细调查大学生体质测试的测试信息管理系统要处理的所有对象&#xff0c;通过充分了解大学生体质测试管理系统的工作流程&#xff0c;明确使用者的各种需求&#xff0c;充分思考之后可能扩充和改变的情况&#xff0c;然后在这个基础上来设计数据库。

论文笔记--TinyBERT: Distilling BERT for Natural Language Understanding

论文笔记--TinyBERT: Distilling BERT for Natural Language Understanding 1. 文章简介2. 文章概括3 文章重点技术3.1 Transformer Distillation3.2 两阶段蒸馏 4. 数值实验5. 文章亮点5. 原文传送门6. References 1. 文章简介 标题&#xff1a;TinyBERT: Distilling BERT fo…

赛效:如何用在线压缩GIF图片

1&#xff1a;在电脑网页上打开并登录快改图&#xff0c;点击左侧菜单栏里的“GIF压缩”。 2&#xff1a;点击页面中间的上传按钮&#xff0c;将电脑本地的GIF文件上传上去。 3&#xff1a;GIF文件上传成功后&#xff0c;设置下方压缩设置&#xff0c;点击右下角“开始压缩”。…

数据结构(王卓版)——线性表

数据的存储结构之线性表 1、线性表的定义和特点

java后端开发环境搭建 mac

在mac pro上搭建一套java 后端开发环境&#xff0c;主要安装的内容有&#xff1a;jdk、maven、git、tomcat、mysql、navicat、IntelliJ、redis。 本人mac pro的系统为mac OS Monterey 12.6.7&#xff0c;主机的硬件架构为x86_64。 左上角关于本机查看系统版本&#xff1b;终端…

前端框架Layui实现动态树效果(书籍管理系统左侧下拉列表)

目录 一、前言 1.什么是树形菜单 2.树形菜单的使用场景 二、案例实现 1.需求分析 2.前期准备工作 ①导入依赖 ②工具类 BaseDao&#xff08;通用增删改查&#xff09; BuildTree(完成平级数据到父子级的转换) ResponseUtil&#xff08;将数据转换成json格式进行回显&…

数据可视化之Tableau可视化||绘制标靶图

标靶图是一种用于评估、测试和优化计算机视觉算法的基准测试工具。它通常由多个具有不同特征的目标物体组成,如车辆、行人、交通信号灯等,同时包括各种不同的复杂场景,如城市街道、高速公路和人行道等。通过使用标靶图,研究人员可以检验算法的准确性、速度和适应性,同时拓…

由于找不到d3dx9_43.dll,有什么可靠的修复方法?

由于找不到d3dx9_43.dll&#xff0c;无法继续执行代码&#xff0c;这种情况大家是否有遇见过&#xff1f;其实就算没遇到过&#xff0c;大家应该也有遇到别的dll文件丢失吧&#xff1f;道理都一样&#xff0c;都是dll文件丢失&#xff0c;我们只需要把它给修复就可以了&#xf…

JVM的类加载机制和垃圾回收机制

目录 类加载机制类加载机制的步骤加载验证准备解析初始化 双亲委派模型工作原理双亲委派模型的优点 垃圾回收机制死亡对象的判断可达性分析算法可达性分析算法的缺点引用计数算法循环引用问题 垃圾回收算法标记-清除算法复制算法标记-整理算法分代算法 类加载机制 对于任意一个…

Antd List组件增加gutter属性后出现横向滚动,如何解决

第一次使用ant design的List列表组件&#xff0c;设置gutter间隔属性后&#xff0c;页面出现了横向滚动条&#xff0c;查阅文档发现是由于加间隔后导致容器宽度被撑开&#xff0c;ant design官方默认给外层容器加了margin-left和margin-right 解决方法是在外层容器预留一定的pa…

【sql注入-堆叠注入】多语句执行、结合其他注入

目录 堆叠注入 一、语法介绍 二、漏洞示例 三、常见形式 网络安全O 堆叠注入 一、语法介绍&#xff1a; 版本&#xff1a; 可以影响几乎所有的关系型数据库 原理&#xff1a; 将多条语句堆叠在一起进行查询&#xff0c;且可以执行多条SQL语句 语句之间以分号(;)隔开&#…

图像分类——模型微调

目录 微调热狗识别获取数据集模型构建与训练 微调 热狗识别 获取数据集 import tensorflow as tf import pathlibtraindirhotdog/train testdirhotdog/test image_gentf.keras.preprocessing.image.ImageDataGenerator(rescale1/255) train_data_genimage_gen.flow_from_direc…