springboot Ip浏览器信息

ip2region

ip2region 是什么?

狮子的魂/ip2region - 码云 - 开源中国 (gitee.com)

官方:ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java,php,c,python,nodejs,golang,c#等查询绑定和Binary,B树,内存三种查询算法

其实就是一个库,用于 IP地址解析定位用的,支持很多客户端,速度很快也不占内存,目前github已经到了10k star 了

特性:

速度快,内置三种查询算法,支持毫秒级查询,全部的查询客户端单次查询都在 0.x 毫秒级别,内置了三种查询算法

  • memory 算法:整个数据库全部载入内存,单次查询都在0.1x毫秒内,C语言的客户端单次查询在0.00x毫秒级别。
  • binary 算法:基于二分查找,基于ip2region.db文件,不需要载入内存,单次查询在0.x毫秒级别。
  • b-tree 算法:基于btree算法,基于ip2region.db文件,不需要载入内存,单词查询在0.x毫秒级别,比binary算法更快。

准确率高,数据聚合多个供应商的数据
体积小,空间优化形成了仅仅几兆的 ip2region.db 文件
支持多客户端,支持很多客户端,java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua、lua_c, nginx
它的数据聚合了一些知名ip到地名查询提供商的数据,例如:(如果一下开放API或者数据都不给开放数据时ip2region将停止数据的更新服务)

淘宝IP地址库, http://ip.taobao.com/
GeoIP, https://geoip.com/
纯真IP库, http://www.cz88.net/

使用

我们这里不导入官方的依赖,我们导入mica-ip2region依赖,mica-ip2regionip2region 的封装,方便 spring boot 用户使用。

mica: Spring Cloud 微服务开发核心工具集。 - Gitee.com

导入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
     
        <dependency>
            <groupId>net.dreamlugroupId>
            <artifactId>mica-ip2regionartifactId>
            <version>2.6.8version>
        dependency>

        <dependency>
            <groupId>cn.hutoolgroupId>
            <artifactId>hutool-allartifactId>
            <version>5.8.4version>
        dependency>
    dependencies>

编写一个浏览器工具类

这里有三个名词,分别是

  • X-Forwarded-For一个 HTTP 扩展头部,主要是为了让 Web 服务器获取访问用户的真实 IP 地址。每个 IP 地址,每个值通过逗号+空格分开,最左边是最原始客户端的 IP 地址,中间如果有多层代理,每⼀层代理会将连接它的客户端 IP 追加在 X-Forwarded-For 右边。
  • X-Real-IP:一般只记录真实发出请求的客户端IP
  • Proxy-Client-IP:这个一般是经过 Apache http 服务器的请求才会有,用 Apache http 做代理时一般会加上 Proxy-Client-IP 请求头
  • WL-Proxy-Client-IP:也是通过 Apache http 服务器,在 weblogic 插件加上的头。

在我们获取到用户的 IP 地址后,那么就可以获取对应的 ip 信息了

@Component
public  class BrowserUtil {
    private static final String UNKNOWN = "unknown";

    /**
     * 根据请求获取ip地址
     */
    public String getIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        String comma = ",";
        String localhost = "127.0.0.1";
        if (ip.contains(comma)) {
            ip = ip.split(",")[0];
        }
        if (localhost.equals(ip)) {
            // 获取本机真正的ip地址
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
            }
        }
        return ip;
    }


    public JSONObject getBrowser(HttpServletRequest request) {
        String browser = request.getHeader("User-Agent");//获取浏览器信息
        UserAgent ua = UserAgentUtil.parse(browser);
        String browserType = ua.getBrowser().toString();
        String version = ua.getVersion();
        String engine = ua.getEngine().toString();
        String engineVersion = ua.getEngineVersion();
        String os = ua.getOs().toString();
        String platform = ua.getPlatform().toString();
        Integer mobile = ua.isMobile() ? 1 : 0;
        JSONObject json = new JSONObject();
        json.set("browserType", browserType).set("platform", platform).set("mobile", mobile).set("os", os).set("platform", platform).set("version", version)
                .set("engine",engine).set("engineVersion", engineVersion);
        return json;
    }
}

编写控制类

@RestController
@RequestMapping("/browser")
public class IpController {
   @Autowired
    BrowserUtil browserUtil;
    @Autowired
    private Ip2regionSearcher ip2regionSearcher; // 核心处理类,具体为什么可以直接 @Autowired,下面原理来说

    @GetMapping("/getAddress")
    public ResponseEntity<Object> address(HttpServletRequest request) throws IOException {
        String ip = browserUtil.getIp(request);
        IpInfo ipInfo = ip2regionSearcher.memorySearch(ip); // 根据ip地址获取到address
        JSONObject entries = new JSONObject();
        if (ipInfo != null) {
            String country = ipInfo.getCountry();
            String province = ipInfo.getProvince();
            String city = ipInfo.getCity();
            String isp = ipInfo.getIsp();
            entries.set("country", country);
            entries.set("province", province);
            entries.set("city", city);
            entries.set("isp", isp);
            entries.set("ip", ip);
        }
        return new ResponseEntity<>(entries, HttpStatus.OK);
    }

    @GetMapping("/getAddressByIp")
    public ResponseEntity<Object> addressByIp(@RequestParam("ip") String ip) throws IOException {
        IpInfo ipInfo = ip2regionSearcher.binarySearch(ip); // 根据ip地址获取到address
        assert ipInfo != null;
        JSONObject entries = new JSONObject();
        if (ipInfo != null) {
            String country = ipInfo.getCountry();
            String province = ipInfo.getProvince();
            String city = ipInfo.getCity();
            String isp = ipInfo.getIsp();
            entries.set("country", country);
            entries.set("province", province);
            entries.set("city", city);
            entries.set("isp", isp);
            entries.set("ip", ip);
        }
        return new ResponseEntity<>(entries, HttpStatus.OK);
    }
    @GetMapping("/getBrowserInfo")
    public JSONObject getBrowser(HttpServletRequest request) throws IOException {
        return browserUtil.getBrowser(request);
    }

    //使用hutool工具调用纯真ip接口
    @GetMapping("/cz88")
    public JSONObject cs88(@RequestParam String ip) {
        String fullUrl="https://www.cz88.net/api/cz88/ip/base?ip="+ip;
        String result= HttpUtil.createGet(fullUrl).execute().body();
        //hutool工具JSON字符串解析
        return JSONUtil.parseObj(result);
    }
}

测试

image-20220708151601708

springboot Ip浏览器信息_第1张图片

springboot Ip浏览器信息_第2张图片

springboot Ip浏览器信息_第3张图片

Docker部署

idea使用Dockerfile创建镜像

文件内容

FROM openjdk:latest

EXPOSE 9956

ADD target/ipBelongingPlace-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'

ENTRYPOINT ["nohup","java","-jar","/app.jar","&"]

构建镜像

springboot Ip浏览器信息_第4张图片

springboot Ip浏览器信息_第5张图片

点击Run运行即可,这样就创建完成了镜像

运行镜像

docker run -d -p 9956:9956 --name bootIp springboot-ip:1.0

image-20220708164814680

日志:

springboot Ip浏览器信息_第6张图片

测试:

windowsDocker

springboot Ip浏览器信息_第7张图片

服务器Docker

springboot Ip浏览器信息_第8张图片

方法接口文档

GET 根据发送请求直接查询ip

GET /browser/getAddress
{
"city":"内网IP",
"isp":"内网IP",
"ip":"172.17.0.1"
}

返回结果

状态码 状态码含义 说明 数据模型
200 OK 成功 Inline

GET 根据发送请求查询浏览器信息

GET /browser/getBrowserInfo

如果使用apifox等测试工具是没有信息的

{
  "browserType": "Unknown",
  "platform": "Unknown",
  "mobile": 0,
  "os": "Unknown",
  "engine": "Unknown"
}

返回结果

状态码 状态码含义 说明 数据模型
200 OK 成功 Inline

GET 使用ip2region依赖查询ip

GET /browser/getAddressByIp

请求参数

名称 位置 类型 必选 说明
ip query string none
{
"country":"中国",
"province":"上海",
"city":"上海",
"isp":"联通",
"ip":"220.248.12.158"
}

返回结果

状态码 状态码含义 说明 数据模型
200 OK 成功 Inline

GET 使用纯真ip库查询ip

GET /browser/cz88

请求参数

名称 位置 类型 必选 说明
ip query string none
{
  "code": 200,
  "success": true,
  "message": "操作成功",
  "data": {
    "ip": "103.216.43.5",
    "countryCode": "CN",
    "country": "中国",
    "province": "北京",
    "city": "北京",
    "districts": "朝阳区",
    "isp": "皓宽网络",
    "geocode": "156011001005",
    "netWorkType": "专线用户",
    "mbRate": "暂未发现",
    "score": "58%",
    "honeypot": "暂未发现",
    "netAddress": "登录查看",
    "actionAddress": [
      "中国-北京-北京-朝阳区"
    ],
    "company": "暂未发现",
    "locations": [
      {
        "latitude": "39.92**",
        "longitude": "116.44**",
        "radius": 34132
      }
    ],
    "openPorts": [],
    "domains": [],
    "breadRateMap": {
      "RuijieNe": "0.191",
      "其他": "0.500",
      "Tp-LinkT": "0.309"
    },
    "deviceRateMap": {
      "安卓": "0.677",
      "iOS": "0.323"
    }
  },
  "time": "2022-07-08 16:53:49"
}

返回结果

状态码 状态码含义 说明 数据模型
200 OK 成功 Inline

博客详情 (warmwood.xyz)

你可能感兴趣的:(笔记,springboot,spring,boot,tcp/ip,后端)