全部
常见问题
产品动态
精选推荐

通过IP获取访问用户位置,处理用户注册异常

管理 管理 编辑 删除

近期,有测试童靴跟我反馈说是新用户手机号注册时,后端抛出了异常,无法正常注册。异常如下

cc965202306300943065909.png

我们可以看到,问题出在IPUtil这个工具类中

经过排查我也定位到问题点所在,是使用第三方通过IP获取访问用户位置时出了问题。这个问题会在Java多商户中出现

我们使用的第三方是淘宝IP地址库,这个第三方不要任何引入跟配置,简单好用。

但是,问题来了,官方有一个通告:

下线通告: 本iP库查询工具将于2022年3月31日起永久关停,届时将不提供任何的IP库查询功能。

3d299202306300947497842.png

也就是说官方虽然目前暂未关停此接口,但说不好什么时候就会不可用了。

针对与当前的这种情况,我这里给大家提供几种解决方案:

目标代码

34955202306301001522174.png

方案一:

针对于不需要在用户注册时获取用户访问地址的情况,也是最简单的方法,直接注释掉这里

d96eb202306301002592915.png

方案二:

经过我的测试,上边淘宝第三方IP地址库的情况,目前只是偶尔一段时间会出现,

我们在这里做try catch处理,让用户在ip这里出问题时,可以正常进行注册服务

cb0f4202306301006042261.png

方案三:

我为大家找个一种替代方案:Ip2region

Ip2region是一个基于Java的IP地址定位库,提供了快速而准确的IP查询服务。它将全球IP地址划分为多级区域,可以根据IP地址获取对应的省市区信息、运营商等详细信息。

官方地址: https://github.com/lionsoul2014/ip2region

使用方式:引入Maven仓库:

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.7.0</version>
</dependency>

代码示例:

实体类

/**
 * @ClassName IpLocation
 * @Description IP位置对象
 * @Author HZW
 * @Date 2023/6/29 11:01
 * @Version 1.0
 */
public class IpLocation {

//    @ApiModelProperty("ip地址")
    private String ip;

//    @ApiModelProperty("国家")
    private String country;

//    @ApiModelProperty("省")
    private String province;

//    @ApiModelProperty("省")
    private String city;

//    @ApiModelProperty("服务商")
    private String isp;

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getIsp() {
        return isp;
    }

    public void setIsp(String isp) {
        this.isp = isp;
    }

    @Override
    public String toString() {
        return "IpLocation{" +
                "ip='" + ip + '\'' +
                ", country='" + country + '\'' +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", isp='" + isp + '\'' +
                '}';
    }
}

工具类

/**
 * @ClassName IpUtil
 * @Description TODO
 * @Author HZW
 * @Date 2023/6/29 11:09
 * @Version 1.0
 */
public class IpUtil {

    /**
     * 字符常量0
     */
    private static final String ZERO = "0";
    /**
     * 本级ip
     */
    private static final String LOCALHOST = "127.0.0.1";

    /**
     * 获取客户端的IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (LOCALHOST.equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }
        // 对于通过多个代理转发的情况,取第一个非unknown的IP地址。
        // 这里假设第一个IP为真实IP,后面的为代理IP。
        if (ipAddress != null && ipAddress.length() > 15) {
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /**
     * 根据iP获取归属地信息
     */
    public static IpLocation getLocation(String ip) {
        IpLocation location = new IpLocation();
        location.setIp(ip);
        try (InputStream inputStream = IpUtil.class.getResourceAsStream("/ip2region/ip2region.xdb");) {
            byte[] bytes = IoUtil.readBytes(inputStream);
            Searcher searcher = Searcher.newWithBuffer(bytes);
            String region = searcher.search(ip);
            if (StrUtil.isAllNotBlank(region)) {
                // xdb返回格式 国家|区域|省份|城市|ISP,
                // 只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0
                String[] result = region.split("\\|");
                location.setCountry(ZERO.equals(result[0]) ? StrUtil.EMPTY : result[0]);
                location.setProvince(ZERO.equals(result[2]) ? StrUtil.EMPTY : result[2]);
                location.setCity(ZERO.equals(result[3]) ? StrUtil.EMPTY : result[3]);
                location.setIsp(ZERO.equals(result[4]) ? StrUtil.EMPTY : result[4]);
            }
            searcher.close();
        } catch (Exception e) {
            System.out.println("ip地址解析异常,error:" + e);
            return location;
        }
        return location;
    }
}

在官网地址,将data目录下的ip2region.xdb文件复制到resource下。

d1422202306301010402971.png

测试:

/**
 * @ClassName IpMain
 * @Description TODO
 * @Author HZW
 * @Date 2023/6/29 11:08
 * @Version 1.0
 */
public class IpMain {

    public static void main(String[] args) {
//        String ip = "192.168.31.164";
        String ip = "219.145.115.165";
        IpLocation location = IpUtil.getLocation(ip);
        System.out.println(location.toString());
    }

}

结果

dbba6202306301011506432.png

当然这里只是ip2region的一个Demo,在ip2region官方也有不同的使用方法,大家可以自己接入。

crmeb的ip2region接入会随同不久后Java多商户V1.3版本的上线一同更新,懒得动手的同学可以到时候一起更新版本。

❄指缝de阳光 最后编辑于2023-06-30 10:19:17

快捷回复
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
回复从新到旧

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest==1? '取消推荐': '推荐'}}
{{item.floor}}#
{{item.user_info.title}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
{{item.like_count}}
{{item.showReply ? '取消回复' : '回复'}}
删除
回复
回复

{{itemc.user_info.nickname}}

{{itemc.user_name}}

作者 管理员 企业

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}   {{itemc.ip_address}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
回复
回复
查看更多
回复
回复
1241
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

❄指缝de阳光 管理员
暂无简介

回答

27

发布

3

经验

355

快速安全登录

使用微信扫码登录
{{item.label}} {{item.label}} {{item.label}} 板块推荐 常见问题 产品动态 精选推荐 首页头条 首页动态 首页推荐
加精
取 消 确 定
回复
回复
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定

微信登录/注册

切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服

CRMEB咨询热线 咨询热线

400-8888-794

微信扫码咨询

CRMEB开源商城下载 开源下载 CRMEB官方论坛 帮助文档
返回顶部 返回顶部
CRMEB客服