Java获取真实ip以及判断ip是否在指定范围
Posted 老周聊架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java获取真实ip以及判断ip是否在指定范围相关的知识,希望对你有一定的参考价值。
欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。
我们平时请求一些资源,对客户端和服务器的域名和ip应该再熟悉不过了;前台地址栏域名请求资源,域名会通过DNS解析器把域名解析成ip,但有时候我们后台得到不止一个ip,这是因为加了类似有反向代理功能的nginx,所以我们要得到真实的ip,自己要在后台做逻辑校验即可。
1、获取真实ip
下面来看Java获取真实ip的代码:
/**
* 获取真实的IP
* @param request
* @return
*/
public static String getIp(HttpServletRequest request)
String ip = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip))
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = ip.indexOf(",");
if (index != -1)
return ip.substring(0,index);
else
return ip;
ip = request.getHeader("X-Real-IP");
if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip))
return ip;
return request.getRemoteAddr();
通过HttpServletRequest
获取头部信息getHeader()
,有两种情况,一个反向代理的,一个真实ip请求;作出相应的处理即可得到真实的ip。
2、 判断ip是否在指定范围
/**
* 判断IP是否在指定范围
* @param ipStart
* @param ipEnd
* @param ip
* @return
*/
public static boolean ipIsValid(String ipStart,String ipEnd, String ip)
if (StringUtils.isEmpty(ipStart))
throw new NullPointerException("起始IP不能为空!");
if (StringUtils.isEmpty(ipEnd))
throw new NullPointerException("结束IP不能为空!");
if (StringUtils.isEmpty(ip))
throw new NullPointerException("IP不能为空!");
ipStart = ipStart.trim();
ipEnd = ipEnd.trim();
ip = ip.trim();
final String REGX_IP = "((25[0-5]|2[0-4]\\\\d|1\\\\d2|[1-9]\\\\d|\\\\d)\\\\.)3(25[0-5]|2[0-4]\\\\d|1\\\\d2|[1-9]\\\\d|\\\\d)";
final String REGX_IPB = REGX_IP + "\\\\-" + REGX_IP;
if (!ipStart.matches(REGX_IP) || !ip.matches(REGX_IP) || !ipEnd.matches(REGX_IP))
return false;
String[] sips = ipStart.split("\\\\.");
String[] sipe = ipEnd.split("\\\\.");
String[] sipt = ip.split("\\\\.");
long ips = 0L, ipe = 0L, ipt = 0L;
for (int i = 0; i < 4; ++i)
ips = ips << 8 | Integer.parseInt(sips[i]);
ipe = ipe << 8 | Integer.parseInt(sipe[i]);
ipt = ipt << 8 | Integer.parseInt(sipt[i]);
if (ips > ipe)
long t = ips;
ips = ipe;
ipe = t;
return ips <= ipt && ipt <= ipe;
相信大家这段代码也都看得懂!
这里我说一下ips = ips << 8 | Integer.parseInt(sips[i]);
代码,像ip我们一般不好直接比较大小,业界一般都是把它们四段不同的相应的分割出来,然后转化成整形,再通过位运算|
以及左移符号<<
来得到相应的ip的整型值。
下面唠叨两句:
&
和 |
既是逻辑运算符也是位运算符,而&&
和||
只是逻辑运算符。
一、逻辑运算符
(1)当&与&&同为逻辑运算符时,它们都用于连接两个Boolean类型的表达式,当&和&&的两端表达式同时为真时,表达式的结果为真,只要有一端为假,那么表达式结果为假。从用法上来看,&和&&并没有什么区别,比如我们可以写两个表达式:
3>5&3>2; 3>5&&3>2;
两个运算符都可以这么用,但是不同的是,当在判断这个表达式的真或假的时候,两者的判断次数不同;
当使用&运算符: 计算机在判断表达式的值的时候,先判断3>5 的值为假,然后再判断3>2的结果为真,于是最后的结果是 假&真 为假;
但是当我们使用&&运算符的时候:计算机先判断3>5 的值为假,此时表达式的结果一定为假,所以计算机就不再往下判断了,判定表达式结果为假。
逻辑运算符&与&&的区别是:
- & 无论左边结果是什么,右边还是继续运算;
- &&当左边为假,右边不再进行运算。
但是两者的结果是一样的。
(2)当|
和||
的两端表达式同时为假时,表达式的结果为假,只要有一端为真,那么表达式结果为真。
所以同理,我们可以知道|
与||
的区别:
|
无论左边结果是什么,右边还是继续运算;||
当左边为真,右边不再进行运算。
但是两者的结果是一样的。
所以&&和||是比较高效那么一点点。
二、&
和 |
做位运算符,做二进制位之间的与运算:
比如:
6&3=110&011=010=2
6|3=110|011=111=7
关于java运算符更深入的了解可以看这篇博文:java运算符 与(&)、非(~)、或(|)、异或(^)
以上是关于Java获取真实ip以及判断ip是否在指定范围的主要内容,如果未能解决你的问题,请参考以下文章