前言
在SpringBoot应用程序中,获取用户的IP地址信息是常见需求。通过分析请求头中的"X-Forwarded-For"字段,可以获取到真实的客户端IP地址。这对于日志记录、流量分析以及安全审计等场景非常有用。
一、IP工具类
@Slf4j
@Component
public class IpUtil {
private static DbSearcher searcher;
private static Method method;
public static String getIpAddress(HttpServletRequest request) {
String ipAddress = request.getHeader("X-Real-IP");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("x-forwarded-for");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
//根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
log.error("getIpAddress exception:", e);
}
assert inet != null;
ipAddress = inet.getHostAddress();
}
}
log.info("ip:{}",ipAddress);
return ipAddress;
// return StringUtils.substringBefore(ipAddress, ",");
}
@PostConstruct
private void initIp2regionResource() throws Exception {
InputStream inputStream = new ClassPathResource("/ip/ip2region.db").getInputStream();
byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);
DbConfig dbConfig = new DbConfig();
searcher = new DbSearcher(dbConfig, dbBinStr);
method = searcher.getClass().getMethod("memorySearch", String.class);
}
public static String getIpSource(String ipAddress) {
if (ipAddress == null || !Util.isIpAddress(ipAddress)) {
log.error("Error: Invalid ip address");
return "";
}
try {
DataBlock dataBlock = (DataBlock) method.invoke(searcher, ipAddress);
String ipInfo = dataBlock.getRegion();
if (!StringUtils.isEmpty(ipInfo)) {
ipInfo = ipInfo.replace("|0", "");
ipInfo = ipInfo.replace("0|", "");
return ipInfo;
}
} catch (Exception e) {
log.error("getCityInfo exception:", e);
}
return "";
}
public static String getIpProvince(String ipSource) {
String[] strings = ipSource.split("\\|");
if (strings[1].endsWith("省")) {
return StringUtils.substringBefore(strings[1], "省");
}
return strings[1];
}
public static UserAgent getUserAgent(HttpServletRequest request) {
return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
}
}
二、ip2region.db文件(百度网盘下载)
链接:https://pan.baidu.com/s/1-99YdE1e92Z5t-_h7mB6xg
提取码:31fv
三、使用示例
@Autowired
private HttpServletRequest request;
@Test
public void getUserIp() {
//ip
String ipAddress = IpUtil.getIpAddress(request);
//来源
String ipSource = IpUtil.getIpSource(ipAddress);
UserAgent userAgent = IpUtil.getUserAgent(request);
//获取浏览器名称
String browser = userAgent.getBrowser().getName();
//操作系统
String os = userAgent.getOperatingSystem().getName();
}
四、结束语
需要注意的是,如果用户通过代理服务器访问应用程序,则"X-Forwarded-For"字段可能包含多个IP地址,需要结合其他因素来判断最接近客户端的真实IP地址。同时,为了保护用户隐私和安全,获取IP地址时应遵循相关法律法规和隐私政策。