Java实现通过IP获取IP归属地的方法(离线+在线)

 更新时间:2023年10月17日 11:16:26   作者:拄杖盲学轻声码  
我们都知道安全攻击都是在某台客户机上执行某些恶意操作致使服务端响应异常崩溃亦或响应数据被篡改,首先我想到的是对访问的web端做一个IP的校验,那么我们首先得知道客户端的IP是多少,接下来此文重点介绍如何获得,需要的朋友可以参考下

【写在前面】

编撰这篇文章还得从之前做安全业务需求说起,我们都知道安全攻击都是在某台客户机上执行某些恶意操作(sql注入,DoS/DDoS攻击),致使服务端响应异常崩溃亦或响应数据被篡改,那么怎么去阻止这些东西呢?

首先我想到的是对访问的web端做一个IP的校验(好比阿里云服务器的安全组设置),建立一些白名单,这样能在很大程度上做到一个限制,其实在服务端也应该要开启防火墙、设置权限等。那么我们首先得知道客户端的IP是多少。接下来此文重点介绍如何获取。

1、如何获取客户端访问IP

其实获取IP是最简单的,因为只要有请求的话,都会存放在session里面的,只要通过下面这句话就可以拿到你所需要的IP,但是如何知道别人访问你的服务器呢,这个时候就需要您自己去写一个监听事件listen;

获取IP方式如下代码即可:

HttpSession session = request.getSession(false);
if (session == null) {
    session = request.getSession();
    System.out.println("session:" + session + "创建成功");
    session.setAttribute("ip", request.getRemoteAddr());
    System.out.println("----访问的IP是:"+request.getRemoteAddr()+"----");
}

控制台输出:

在这里插入图片描述

2、如何通过IP获取归属地(离线+在线)

通过上面的方式拿到了IP地址,那么我想知道是哪些地方的人访问了我们的系统的话这就需要后台去进行查询了,这才是这篇文章的核心:

2.1 离线模式

主要是通过自己本地的离线库来实现查找的,有个弊端就是需要不断的更新。

第一步:下载离线包ip2region.xdb

首先下载一个离线的IP归属映射包ip2region.xdb,没有的可以去我的百度云盘上下载

下载地址如下:

链接:https://pan.baidu.com/s/1l_Gfhl0TVPYXvpK9QSiXyw

提取码:hdd6

第二步:引入离线包

将我们的离线包放在resources目录下,如下图所示:

在这里插入图片描述

Maven引入

打开项目中的pom.xml文件,将下面的代码复制到里面去(如果有则忽略):

<!-- ip2region  -->
    <dependency>
      <groupId>org.lionsoul</groupId>
      <artifactId>ip2region</artifactId>
      <version>2.6.5</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.9</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5</version>
    </dependency>

开始引入时候可能会报红,需要你自己去更新一下maven库

在这里插入图片描述

没有报红表示本地引入成功。

Pom.xml引入静态打包(特别关键,不然会报错)

[Xxx/ip2region.xdb] cannot be opened because it does not exist

<resource>
  <directory>src/main/resources</directory>
  <includes>
    <include>jdbc.properties</include>
    <include>*.xml</include>
    <include>ipdb/*.xdb</include>
  </includes>
</resource>

主要是在构建的时候我们java会变成class文件进行编译,一些静态资源需要自己手动去加才能打到jar包里面去。

第三步:代码实现

控制台效果如下所示(国内国外的都有):

在这里插入图片描述

核心实现代码(记得要引入一些依赖包哟):

String dbPath = "/ipdb/ip2region.xdb";
try {
    InputStream inputStream = new ClassPathResource(dbPath).getInputStream();
    byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);
    // 创建一个完全基于内存的查询对象
    searcher = Searcher.newWithBuffer(dbBinStr);
} catch (Exception e) {
    System.out.printf("failed to create content cached searcher: %s\n", e);
}
//把ip2r
String address = "";
try {
    address = searcher.search("66.249.79.193");
} catch (Exception e) {
    throw new RuntimeException(e);
}
System.out.println("=== 访问者的地址为:"+address+" === ");

到这里我们就只要维护好那个离线包文件就可以,定时更新一下。

2.2 在线模式

主要通过别人或者官网提供的API接口去实现查询的功能,有个弊端就是特别依赖别人的服务器,万一别人服务器挂了就访问不了了。

具体实现效果和2.1离线模式介绍的一样

在这里插入图片描述

主要实现我封装到一个java类里面,写了一些特定的方法;

如下所示:

public static String getAddress(String ip) {
    try {
        URL realUrl = new URL("http://whois.pconline.com.cn/ipJson.jsp?ip=" + ip + "&json=true");
        HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
        conn.setRequestMethod("GET");
        conn.setUseCaches(false);
        conn.setReadTimeout(6000);
        conn.setConnectTimeout(6000);
        conn.setInstanceFollowRedirects(false);
        int code = conn.getResponseCode();
        StringBuilder sb = new StringBuilder();
        String ipaddr = "";
        if (code == 200) {
            InputStream in = conn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            ipaddr = ip + "=" + sb.substring(sb.indexOf("addr") + 7, sb.indexOf("regionNames") - 3);
        }
        return ipaddr;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

调用地方如下所示:

String address = IpAddressUtils.getAddress("66.249.79.193");
System.out.println("=== (在线)访问者的地址为:"+address+" === ");

3、推荐方式,先离线后在线

【重要】其实我们可以结合两个使用一起,先采用离线,如果发现为null的话则调用在线查询的方式。这样在一定的程度上能够保证数据的完整性,都有不足的话就互补一下;如下所示逻辑:

System.out.println("--- (在线+离线)访问者的IP为:66.249.79.193 --- ");
        //================离线模式获取=start====================//
        String dbPath = "/ipdb/ip2region.xdb";
        try {
            InputStream inputStream = new ClassPathResource(dbPath).getInputStream();
            byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);
            // 创建一个完全基于内存的查询对象
            searcher = Searcher.newWithBuffer(dbBinStr);
        } catch (Exception e) {
            System.out.printf("failed to create content cached searcher: %s\n", e);
        }
        //把ip2r
        String address = "";
        try {
            address = searcher.search("221.231.220.212");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
//        String address = IpAddressUtils.getCityInfo("66.249.79.193");
        System.out.println("=== (离线)访问者的地址为:"+address+" === ");
        //================离线模式获取=end====================//
        //======================在线模式获取 start========================//
        if("".equals(address)){
            address = IpAddressUtils.getAddress("66.249.79.193");
            System.out.println("=== (在线)访问者的地址为:"+address+" === ");
        }
        //======================在线模式获取 end========================//

4、最后

以上就是Java实现通过IP获取IP归属地的方法(离线+在线)的详细内容,更多关于Java获取IP归属地的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot 配置 okhttp3的操作

    SpringBoot 配置 okhttp3的操作

    这篇文章主要介绍了SpringBoot 配置 okhttp3的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • java super关键字知识点详解

    java super关键字知识点详解

    在本篇文章里小编给大家整理的是一篇关于java super关键字知识点详解内容,有兴趣的朋友们可以参考下。
    2021-01-01
  • java如何将实体类转换成json并在控制台输出

    java如何将实体类转换成json并在控制台输出

    这篇文章主要介绍了java如何将实体类转换成json并在控制台输出问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Java MyBatis之Mapper代理详解

    Java MyBatis之Mapper代理详解

    这篇文章主要介绍了Java web中MyBatis的mapper代理,文中有详细的代码示例,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2023-04-04
  • java设计日历可视化的详细步骤记录

    java设计日历可视化的详细步骤记录

    这篇文章主要给大家介绍了关于java设计日历可视化的相关资料,通过自定义的CircleLabel类来突出显示今天的日期,并使用BorderLayout布局管理窗口组件,文章详细描述了各个类和方法的设计思想和实现逻辑,需要的朋友可以参考下
    2024-12-12
  • 详解spring多线程与定时任务

    详解spring多线程与定时任务

    本篇文章主要介绍了spring多线程与定时任务,详细的介绍了spring多线程任务和spring定时任务,有兴趣的可以了解一下。
    2017-04-04
  • 详解Maven多模块打包遇到的问题解决方法

    详解Maven多模块打包遇到的问题解决方法

    这篇文章主要介绍了详解Maven多模块打包遇到的问题解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Springboot 集成spring cache缓存的解决方案

    Springboot 集成spring cache缓存的解决方案

    这篇文章主要介绍了Springboot 集成spring cache缓存,使用缓存最关键的一点就是保证缓存与数据库的数据一致性,本文给大家介绍最常用的缓存操作模式,对Springboot 集成spring cache缓存操作流程感兴趣的朋友一起看看吧
    2022-06-06
  • 使用IDEA如何打包发布SpringBoot并部署到云服务器

    使用IDEA如何打包发布SpringBoot并部署到云服务器

    这篇文章主要介绍了使用IDEA如何打包发布SpringBoot并部署到云服务器问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java选择排序思路详解

    Java选择排序思路详解

    这篇文章给大家介绍Java选择排序思路详解,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-12-12

最新评论