package com.njcn.gateway.utils; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author hongawen * @version 1.0.0 * @date 2021年05月25日 11:25 */ @Slf4j public class IpUtils { private static final String UNKNOWN = "unknown"; private static final String LOCALHOST_IPV4 = "127.0.0.1"; private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1"; private static final String SEPARATOR = ","; private static final String HEADER_X_FORWARDED_FOR = "x-forwarded-for"; private static final String HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP"; private static final String HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP"; private static final int IP_LEN = 15; /** * 获取用户真实IP地址,不直接使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址, *

* 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢? * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。 *

* 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, * 192.168.1.100 *

* 用户真实IP为: 192.168.1.110 */ public static String getRealIpAddress(ServerHttpRequest request) { HttpHeaders headers = request.getHeaders(); String ipAddress = headers.getFirst(HEADER_X_FORWARDED_FOR); log.error("X-Forwarded-For:"+ipAddress); ipAddress = headers.getFirst("X-Real-IP"); log.error("X-Real-IP:"+ipAddress); ipAddress = headers.getFirst("Proxy-Client-IP"); log.error("Proxy-Client-IP:"+ipAddress); if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) { ipAddress = headers.getFirst(HEADER_PROXY_CLIENT_IP); } if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) { ipAddress = headers.getFirst(HEADER_WL_PROXY_CLIENT_IP); } if (StrUtil.isBlankIfStr(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) { ipAddress = Optional.ofNullable(request.getRemoteAddress()) .map(address -> address.getAddress().getHostAddress()) .orElse(""); if (LOCALHOST_IPV4.equals(ipAddress) || LOCALHOST_IPV6.equals(ipAddress)) { // 根据网卡取本机配置的IP try { InetAddress inet = InetAddress.getLocalHost(); ipAddress = inet.getHostAddress(); } catch (UnknownHostException e) { log.error("解析请求IP失败,{}", Stream.of(e.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining(StrUtil.CRLF))); } } } // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if (ipAddress != null && ipAddress.length() > IP_LEN) { int index = ipAddress.indexOf(SEPARATOR); if (index > 0) { ipAddress = ipAddress.substring(0, index); } } return ipAddress; } /** * 获取客户端端口 */ public static Integer getPort(ServerHttpRequest request) { return request.getRemoteAddress().getPort(); } }