关于 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\\\\.\\\\d1,3\\\\.\\\\d1,3\\\\.\\\\d1,3)|(172\\\\.((1[6-9])|(2\\\\d)|(3[01]))\\\\.\\\\d1,3\\\\.\\\\d1,3)|(192\\\\.168\\\\.\\\\d1,3\\\\.\\\\d1,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字符串函数

常见的几个Qt编程问题的处理(转自QT中文论坛)(挺实用的)

mysql中比较实用的几个函数

shell关于以.分离IP为四个段并调用的几个思路

关于负载均衡的几个知识点