获取客户端IP地址
/**
* 类功能描述:IP 地址工具类
*
* @author: 一月君言
*/
public final class IpUtil {
private static Logger logger = LoggerFactory.getLogger(IpUtil.class);
private static final String IP_UTILS_FLAG = ",";
private static final String UNKNOWN = "unknown";
private static final String LOCALHOST_IP = "0:0:0:0:0:0:0:1";
private static final String LOCALHOST_IP1 = "127.0.0.1";
/**
* 获取ip地址
*
* @param request
* @return
*/
public static String getClientIpAddr(HttpServletRequest request) {
return getClientIpAddr(request, Arrays.asList(
"X-Original-Forwarded-For",
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_CLIENT_IP",
"HTTP_X_FORWARDED_FOR"
).iterator());
}
/**
* 获取IP地址
* <p>
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*
* @param request
* @param headers
* @return
*/
public static String getClientIpAddr(HttpServletRequest request, Iterator<String> headers) {
String ip = null;
try {
// 1. 从 header 中获取ip
while (headers.hasNext()) {
String tmpIp = request.getHeader(headers.next());
if (validateIP(tmpIp)) {
ip = tmpIp;
break;
}
}
//2. 兼容k8s集群获取ip
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (LOCALHOST_IP1.equalsIgnoreCase(ip) || LOCALHOST_IP.equalsIgnoreCase(ip)) {
// 根据网卡取本机配置的IP
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
logger.error("getClientIpAddr error: {}", e);
}
ip = inetAddress.getHostAddress();
}
}
} catch (Exception e) {
logger.error("IpUtil ERROR ", e);
}
// 3. 如果使用代理, "unknown,unknown,192.168.101.1", 则获取第一个非unknown的有效IP字符串,则为真实IP地址
if (StringUtils.isNotEmpty(ip) && ip.contains(IP_UTILS_FLAG)) {
String[] ipList = ip.split(IP_UTILS_FLAG);
for (String ipTemp : ipList) {
if (!UNKNOWN.equalsIgnoreCase(ipTemp)) {
ip = ipTemp;
break;
}
}
}
return ip;
}
/**
* 检测ip 是否合法
*
* @param ip
* @return
*/
public static boolean validateIP(String ip) {
return StringUtils.isNotEmpty(ip) && !UNKNOWN.equalsIgnoreCase(ip);
}
}
判断IP是否是内网IP
注意:这里只是 判断 IP v4。
在项目的 pom中引入 hutool 依赖。 调用 cn.hutool.core.net.NetUtil.isInnerIP(String ipAddress)
即可。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.21</version>
</dependency>
cn.hutool.core.net.NetUtil
/**
* 判定是否为内网IPv4<br>
* 私有IP:
* <pre>
* A类 10.0.0.0-10.255.255.255
* B类 172.16.0.0-172.31.255.255
* C类 192.168.0.0-192.168.255.255
* </pre>
* 当然,还有127这个网段是环回地址
*
* @param ipAddress IP地址
* @return 是否为内网IP
* @see Ipv4Util#isInnerIP(String)
*/
public static boolean isInnerIP(String ipAddress) {
return Ipv4Util.isInnerIP(ipAddress);
}
cn.hutool.core.net.Ipv4Util
/**
* 判定是否为内网IPv4<br>
* 私有IP:
* <pre>
* A类 10.0.0.0-10.255.255.255
* B类 172.16.0.0-172.31.255.255
* C类 192.168.0.0-192.168.255.255
* </pre>
* 当然,还有127这个网段是环回地址
*
* @param ipAddress IP地址
* @return 是否为内网IP
* @since 5.7.18
*/
public static boolean isInnerIP(String ipAddress) {
boolean isInnerIp;
long ipNum = ipv4ToLong(ipAddress);
long aBegin = ipv4ToLong("10.0.0.0");
long aEnd = ipv4ToLong("10.255.255.255");
long bBegin = ipv4ToLong("172.16.0.0");
long bEnd = ipv4ToLong("172.31.255.255");
long cBegin = ipv4ToLong("192.168.0.0");
long cEnd = ipv4ToLong("192.168.255.255");
isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || LOCAL_IP.equals(ipAddress);
return isInnerIp;
}