关于 ip 操作的几个实用函数

Posted sp42a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 ip 操作的几个实用函数相关的知识,希望对你有一定的参考价值。

获取请求 ip

首先是获取客户端请求的 ip。

/**
 * 获取请求 ip
 * 
 * @return 客户端 ip
 */
public String getIp() {
	String ip = getHeader("x-forwarded-for");

	if (!"unknown".equalsIgnoreCase(ip) && ip != null && ip.length() != 0) {
		int index = ip.indexOf(",");

		if (index != -1)
			ip = ip.substring(0, index);

		return ip.startsWith("::ffff:") ? ip.replaceAll("::ffff:", "") : ip;
	}

	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		ip = getHeader("Proxy-Client-IP");

	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		ip = getHeader("WL-Proxy-Client-IP");

	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		ip = getHeader("X-Real-Ip");

	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
		ip = getRemoteAddr();

	return ip.startsWith("::ffff:") ? ip.replaceAll("::ffff:", "") : ip;
}

ip 拦截

其次是 ip 拦截。

// --------------IP 拦截----------------
static LRUCache<String, Boolean> cache = new LRUCache<>(20);

public static boolean isChinaMainlandIp(String ip) {
	Map<String, Object> map = Tools.getIpLocation(ip);
	Object c = map.get("country");

	if (c != null && "中国".equals(c.toString())) {
		Object r = map.get("region");

		if (r != null && ("香港".equals(r.toString()) || "澳门".equals(r.toString()) || "台湾".equals(r.toString()))) {
			return false;
		}

		return true;
	} else {
		return false;
	}
}

public static boolean isChinaMainlandIp_Cache(String ip) {
	Boolean isChinaMainlandIp = cache.get(ip);

	if (isChinaMainlandIp == null) {
		isChinaMainlandIp = isChinaMainlandIp(ip);
		cache.put(ip, isChinaMainlandIp);
	}

	return isChinaMainlandIp;
}

	public static boolean isChinaMainlandIp_Cache(HttpServletRequest req) {
		String ip = req instanceof MvcRequest ? ((MvcRequest) req).getIp() : new MvcRequest(req).getIp();
		return isChinaMainlandIp_Cache(ip);
	}

获取 ip 区域信息

当然也少不了如何获取 ip 区域信息的。这些都是免费的接口。

/**
 * 淘宝 ip 查询,限制得很厉害,不推荐使用
 * 
 * http://blog.zhukunqian.com/?p=1998 http://pv.sohu.com/cityjson?ie=utf-8
 * https://gitee.com/meaktsui/ChinaIpSearch
 * 
 * @param ip IPv4 地址
 * @return 结果信息
 */
public static Map<String, Object> getIpLocation(String ip) {
	Map<String, Object> map = Get.api("https://ip.taobao.com/outGetIpInfo?ip=" + ip);

	if (!map.containsKey(Get.ERR_MSG))
		return map;
	else {
		LOGGER.warning("接口返回不成功 " + map.get(Get.ERR_MSG));
		return map;
	}
}

/**
 * ip 查询
 * 
 * @param ipIPv4 地址
 * @return 结果信息
 */
public static Map<String, Object> getIpLocation2(String ip) {
	Map<String, Object> map = Get.api("http://ip-api.com/json/" + ip + "?lang=zh-CN");

	if (!map.containsKey(Get.ERR_MSG))
		return map;
	else {
		LOGGER.warning("接口返回不成功 " + map.get(Get.ERR_MSG));
		return map;
	}
}

Test

@Test
public void testGetIpLocation() {
//		assertEquals(0, Tools.getIpLocation("35.220.250.107").get("code"));
	assertNotNull(Tools.getIpLocation2("35.220.250.107"));
}

@Test
public void testGetIpLocation2() {
	assertEquals("success", Tools.getIpLocation2("35.220.250.107").get("status"));
}

获取内网 ip 的三种方法

第一种方法,适合可以连接互联网的电脑。

/**
 * 本地 ip 地址缓存
 */
public static String IP;

/**
 * 获取本机 ip,带缓存的
 * 
 * @return 本地 ip 地址
 */
public static String getLocalIp() {
	if (IP == null)
		IP = getLocalHostLANAddress().getHostAddress();

	return IP;
}

/**
 * 获取本机局域网地址
 * 
 * @return 本机局域网地址对象
 */
public static InetAddress getLocalHostLANAddress() {
	InetAddress candidateAddress = null;

	try {
		// 遍历所有的网络接口
		for (Enumeration<?> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
			NetworkInterface iface = (NetworkInterface) ifaces.nextElement();

			// 在所有的接口下再遍历 IP
			for (Enumeration<?> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
				InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();

				if (!inetAddr.isLoopbackAddress()) {// 排除 loopback 类型地址
					if (inetAddr.isSiteLocalAddress())
						return inetAddr;// 如果是 site-local 地址,就是它了
					else if (candidateAddress == null)
						candidateAddress = inetAddr;// site-local 类型的地址未被发现,先记录候选地址
				}
			}
		}

		if (candidateAddress != null)
			candidateAddress = InetAddress.getLocalHost();// 如果没有发现 non-loopback 地址.只能用最次选的方案
	} catch (Exception e) {
		LOGGER.warning(e);
	}

	return candidateAddress;
}

不能连接外网?那么试试下面两个方法。

/**
 * 如果 getLocalHostLANAddress() 放在不能连接公网的环境,那个方法就不适用了,可以使用这个方法
 * 
 * @return 本地 ip 地址
 */
public static String getLocalIp2() {
	try (Socket socket = new Socket();) {
		socket.connect(new InetSocketAddress("baidu.com", 80));
		return socket.getLocalAddress().getHostAddress();
	} catch (IOException e) {
		LOGGER.warning(e);
		return null;
	}
}

/**
 * 第二种方法
 * 
 * @return 本地 ip 地址
 */
public static String getLocalIp3() {
	try (DatagramSocket socket = new DatagramSocket()) {
		socket.connect(InetAddress.getByName("114.114.114.114"), 10002);
		return socket.getLocalAddress().getHostAddress();
	} catch (IOException e) {
		LOGGER.warning(e);
		return null;
	}
}

域名 whois 查询

最后附送域名 whois 查询,这跟 ip 没什么关系。

/**
 * 域名是否已经注册
 * 
 * @deprecated
 * @param domain 域名
 * @return true=可以注册
 * @throws IOException 访问异常
 */
public static boolean isDomianRegisterAvailable(String domain) throws IOException {
	Map<String, String> map = Get.apiXML("http://panda.www.net.cn/cgi-bin/check.cgi?area_domain=" + domain);

	if ("200".equals(map.get("returncode"))) {
		if (map.get("original").startsWith("210"))
			return true; // original=210 : Domain name is available 表示域名可以注册
		else if (map.get("original").startsWith("211"))
			return false;// original=211 : Domain name is not available 表示域名已经注册
		else if (map.get("original").startsWith("212"))
			throw new IOException("域名参数传输错误");
		else
			throw new IOException("未知错误! " + map);
	} else
		throw new IOException("接口返回不成功 " + map);
}

/**
 * 域名 whois 查询 https://www.nowapi.com/api/domain.whois
 * 
 * @param domain 域名
 * @return 域名详情
 */
public static Map<String, String> getWhois(String domain) {
	Map<String, String> map = Get.apiXML("http://api.k780.com/?app=domain.whois&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=xml&domain=" + domain);

	if (!map.containsKey(Get.ERR_MSG))
		return map;
	else {
		LOGGER.warning("接口返回不成功 " + map.get(Get.ERR_MSG));
		return map;
	}
}

/**
 * 判断IP是否内网
 * 
 * @param ip
 * @return true 表示为内网 ip
 */
public static boolean innerIP(String ip) {
    // 很简单的正则判断
	return StrUtil.regTest(
			"^(127\\\\.0\\\\.0\\\\.1)|(localhost)|(10\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3})|(172\\\\.((1[6-9])|(2\\\\d)|(3[01]))\\\\.\\\\d{1,3}\\\\.\\\\d{1,3})|(192\\\\.168\\\\.\\\\d{1,3}\\\\.\\\\d{1,3})$",
			ip);
}

TEST

@Test
public void testGetWhois() {
	Map<String, String> whois = Tools.getWhois("ajaxjs.com");
	System.out.println(whois);
	assertNotNull(whois);
}

@Test
public void testInnerIP() {
	assertTrue(Tools.innerIP("192.168.1.100"));
}

以上是关于关于 ip 操作的几个实用函数的主要内容,如果未能解决你的问题,请参考以下文章

常用js工具类之关于身份证号码验证的几个实用函数

分享几个实用的代码片段(附代码例子)

分享几个实用的代码片段(附代码例子)

分享几个实用的代码片段(第二弹)

分享几个实用的代码片段(第二弹)

自己收集的几个比较实用的Delphi字符串函数