ip类工具
介绍InetAddress
InetAddress是java提供的一个类,用于表示ip地址。它提供了一系列静态方法来获取和操作ip
InetAddress类有两个子类:Inet4Address和Inet6Address,分别用于表示IPv4和IPv6地址。
常用方法
- getLocalHost():获取本地主机的InetAddress对象,即获取本机的IP地址。
- getByName(String host):根据指定的主机名或IP地址字符串,返回对应的InetAddress对象。
- getHostName():获取InetAddress对象对应的主机名。
- getHostAddress():获取InetAddress对象的IP地址字符串。
- isReachable(int timeout):判断InetAddress对象对应的主机是否可达。
- equals(Object obj):判断两个InetAddress对象是否相等。
完整介绍Java-InetAddress、Inet4Address、Inet6Address介绍-CSDN博客
案例:主要是通过它将字符串转化为IntAddress对象,然后再转成Ipv4地址
java
ServerHttpRequest request = exchange.getRequest();
// 获取 IP 地址
String ip1 = getIP(request);
//有时获取到的字符串是ip+端口,裁切端口让字符串为ipv4格式
int position=0;//:的位置
for(int i=0; i<=ip1.length()-1; i++){
if(ip1.charAt(i)==':'){
position=i;
break;
}
}
String ip = ip1.substring(0,position);
log.info("========= 请求的IP地址: " + ip);
//解析ipv4
String ipv4Address = null;
try {
//通过字符串来获取InetAddress对象,然后再转成ipv4地址
InetAddress inetAddress = InetAddress.getByName(ip);
if (inetAddress != null) {
ipv4Address = inetAddress.getHostAddress();
log.info("成功解析Ipv4:{}", ipv4Address);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
网关过滤器和普通过滤器获取ip
网关ServerHttpRequest
下面是自己写的微服务中网关的案例:主要通过获取ipv4地址然后存入redis
java
@Component
@Slf4j
public class ipv4Filter implements GlobalFilter, Ordered {
@Resource
RedisTemplate redisTemplate;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 请求
ServerHttpRequest request = exchange.getRequest();
// 获取 IP 地址
String ip1 = getIP(request);
int position=0;//:的位置
for(int i=0; i<=ip1.length()-1; i++){
if(ip1.charAt(i)==':'){
position=i;
break;
}
}
//有时获取到的字符串是ip+端口,裁切端口让字符串为ipv4格式
String ip = ip1.substring(0,position);
log.info("========= 请求的IP地址: " + ip);
//解析ipv4
String ipv4Address = null;
try {
InetAddress inetAddress = InetAddress.getByName(ip);
if (inetAddress != null) {
ipv4Address = inetAddress.getHostAddress();
log.info("成功解析Ipv4:{}", ipv4Address);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
//获取用户ID
try {
String userInfo = request.getHeaders().get("userInfo").get(0);
Long userId = Long.valueOf(userInfo);
log.info("ip过滤器获取到用户id:{}", userId);
redisTemplate.opsForValue().set(SystemConstant.REDIS_CLOCK_IPV4+userId, ipv4Address,2,TimeUnit.MINUTES);
return chain.filter(exchange);
}catch (Exception e){
// e.printStackTrace();
log.info("未获取到userInfo,有可能是无需登录的路径,直接放行");
return chain.filter(exchange);
}
}
@Override
public int getOrder() {
return 1;
}
//正式模板
// 多次反向代理后会有多个ip值 的分割符
private final static String IP_UTILS_FLAG = ",";
// 未知IP
private final static String UNKNOWN = "unknown";
// 本地 IP
private final static String LOCALHOST_IP = "0:0:0:0:0:0:0:1";
private final static String LOCALHOST_IP1 = "127.0.0.1";
private static String getIP(ServerHttpRequest request){
//获取header
HttpHeaders headers = request.getHeaders();
log.info("========= 请求的headers: " + headers);
// 根据 HttpHeaders 获取 请求 IP地址
String ip = request.getHeaders().getFirst("X-Forwarded-For");
log.info("========= 请求的第一个IP地址: " + ip);
if (ip==null || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("x-forwarded-for");
log.info("========= 请求的第二个IP地址: " + ip);
if (ip != null && ip.length() != 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
if (ip.contains(IP_UTILS_FLAG)) {
ip = ip.split(IP_UTILS_FLAG)[0];
}
}
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeaders().getFirst("X-Real-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddress().toString().substring(1);
}
//TODO 解决ip问题,无法获取当前请求发送的ip
log.info("========= 请求的代理或者路由IP地址: " + ip);
//兼容k8s集群获取ip
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddress().getAddress().getHostAddress();
if (LOCALHOST_IP1.equalsIgnoreCase(ip) || LOCALHOST_IP.equalsIgnoreCase(ip)) {
//根据网卡取本机配置的IP
InetAddress iNet = null;
try {
iNet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
log.error("getClientIp error: ", e);
}
log.info("========= 请求的本地IP地址: " + iNet.getHostAddress());
ip = iNet.getHostAddress();
}
}
return ip;
}
}
普通HttpServletRequest
java
//正式模板
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";
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
//以下两个获取在k8s中,将真实的客户端IP,放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。
ip = request.getHeader("X-Original-Forwarded-For");
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
//获取nginx等代理的ip
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("x-forwarded-for");
}
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
//兼容k8s集群获取ip
if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (LOCALHOST_IP1.equalsIgnoreCase(ip) || LOCALHOST_IP.equalsIgnoreCase(ip)) {
//根据网卡取本机配置的IP
InetAddress iNet = null;
try {
iNet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
log.error("getClientIp error: ", e);
}
ip = iNet.getHostAddress();
}
}
} catch (Exception e) {
log.error("IPUtils ERROR ", e);
}
//使用代理,则获取第一个IP地址
if (!StringUtils.isEmpty(ip) && ip.indexOf(IP_UTILS_FLAG) > 0) {
ip = ip.substring(0, ip.indexOf(IP_UTILS_FLAG));
}
return ip;
}
原文链接
ServerHttpRequest 和 HttpServletRequest区别以及获取IP_serverwebexchange获取ip-CSDN博客
ip获取只能在服务器上测试
ip获取只能在服务器上测试,否则拿到的是回环地址
ip地址转译为字符串存储
实现逻辑:获取ip -> 根据ip获取ipv4和子网掩码字节数组 -> 进行AND运算 -> 保存转译ip
java
@Override
public Result addIpv4() throws UnknownHostException {
Long id=UserContext.getUser();
String ipv4= (String) redisTemplate.opsForValue().get(SystemConstant.REDIS_CLOCK_IPV4+id);
log.info("获取的ip为:{}, id为:{}",ipv4,id);
redisTemplate.delete(SystemConstant.REDIS_CLOCK_IPV4+id);
// 将IP地址和子网掩码解析为InetAddress对象
InetAddress ip = InetAddress.getByName(ipv4);
InetAddress mask = InetAddress.getByName("255.255.255.0");
// 获取IP地址和子网掩码的字节数组
byte[] ipBytes = ip.getAddress();
byte[] maskBytes = mask.getAddress();
// 进行AND运算
byte[] networkBytes = new byte[ipBytes.length];
for (int i = 0; i < ipBytes.length; i++) {
networkBytes[i] = (byte) (ipBytes[i] & maskBytes[i]);
}
//插入
if(ipv4LogMapper.select(ipv4)==null){
ipv4LogMapper.insert(ipv4);
}
String ipAndMask=Base64.getEncoder().encodeToString(networkBytes);
log.info("执行更新打卡ip功能,转义后的ip:{}",ipAndMask);
String clockIp=clockIpMapper.getClockIp(ipAndMask);
if(!(clockIp ==null)){
log.info("已经存在的打卡ip,ip:{},转义后的ip:{}",ipv4,ipAndMask);
return Result.okResult("该网络可以打卡,请重新连接再次刷新,如果不成功请联系管理员");
}
log.info("成功添加可以打卡的公网ip,ip:{},转义后的ip:{}",ipv4,ipAndMask);
clockIpMapper.insertClockIp(ipAndMask);
return Result.okResult("操作成功,请再次尝试打卡,如若不成功请联系管理员");
}
解析的话,同理,直接转译然后与数据库中的ip对比即可(有点暴力
java
//从redis数据库里获取对应的ipv4信息
String ipv4= (String) redisTemplate.opsForValue().get(SystemConstant.REDIS_CLOCK_IPV4+id);
redisTemplate.delete(SystemConstant.REDIS_CLOCK_IPV4+id);
// 将IP地址和子网掩码解析为InetAddress对象
InetAddress ip = InetAddress.getByName(ipv4);
InetAddress mask = InetAddress.getByName("255.255.255.0");
// 获取IP地址和子网掩码的字节数组
byte[] ipBytes = ip.getAddress();
byte[] maskBytes = mask.getAddress();
// 进行AND运算
byte[] networkBytes = new byte[ipBytes.length];
for (int i = 0; i < ipBytes.length; i++) {
networkBytes[i] = (byte) (ipBytes[i] & maskBytes[i]);
}
if(ipv4LogMapper.select(ipv4)==null&&ipv4!=null){
ipv4LogMapper.insert(ipv4);
}
String ipAndMask= Base64.getEncoder().encodeToString(networkBytes);
log.info("子网信息:{}",ipAndMask);
List<String> list=clockIpMapper.getClockIpList();
boolean isClockIp=false;
log.info("list:{}",list);
for(String i:list){
log.info("比对子网信息:{},:{}",ipAndMask, i);
if(ipAndMask.equals(i)) {
isClockIp=true;
break;
}
}