springboot作为后台代码,获取到的登录IP是前台的代理服务器地址,并不是用户的真实IP地址,让我们在做统计的时候无从下手。下面是一个后台获取IP地址的类,本质上没有什么问题,问题在于,Nginx给你的就是一个代理之后的地址,所以你当然获取不到真实的地址了。

package com.**.common.core.utils.ip;

import java.net.InetAddress;

import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;

import com.**.common.core.utils.StringUtils;

import org.springframework.http.HttpHeaders;

import org.springframework.http.server.reactive.ServerHttpRequest;

/**

  • 获取IP方法

  • @author Hxhh

/public class IpUtils{/*

  • 获取客户端IP

  • @param request 请求对象
  • @return IP地址

*/

public static String getIpAddr(HttpServletRequest request)

{

if (request == null)

{

return "unknown";

}

String ip = request.getHeader("x-forwarded-for");

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))

{

ip = request.getHeader("Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))

{

ip = request.getHeader("X-Forwarded-For");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))

{

ip = request.getHeader("WL-Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))

{

ip = request.getHeader("X-Real-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))

{

ip = request.getRemoteAddr();

}

return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);

}

public static String getIpAddr(ServerHttpRequest request) {

HttpHeaders headers = request.getHeaders();

String ip = headers.getFirst("x-forwarded-for");

if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {

// 多次反向代理后会有多个ip值,第一个ip才是真实ip

if (ip.indexOf(",") != -1) {

ip = ip.split(",")[0];

}

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = headers.getFirst("Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = headers.getFirst("WL-Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = headers.getFirst("HTTP_CLIENT_IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = headers.getFirst("HTTP_X_FORWARDED_FOR");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = headers.getFirst("X-Real-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getRemoteAddress().getAddress().getHostAddress();

}

return ip;

}

/**

  • 检查是否为内部IP地址

  • @param ip IP地址
  • @return 结果

/**

  • 检查是否为内部IP地址

  • @param addr byte地址
  • @return 结果

/**

  • 将IPv4地址转换成字节

  • @param text IPv4地址
  • @return byte 字节

*/

public static byte[] textToNumericFormatV4(String text)

{

if (text.length() == 0)

{

return null;

}

byte[] bytes = new byte[4];

String[] elements = text.split("\.", -1);

try

{

long l;

int i;

switch (elements.length)

{

case 1:

l = Long.parseLong(elements[0]);

if ((l < 0L) || (l > 4294967295L))

{

return null;

}

bytes[0] = (byte) (int) (l >> 24 & 0xFF);

bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);

bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);

bytes[3] = (byte) (int) (l & 0xFF);

break;

case 2:

l = Integer.parseInt(elements[0]);

if ((l < 0L) || (l > 255L))

{

return null;

}

bytes[0] = (byte) (int) (l & 0xFF);

l = Integer.parseInt(elements[1]);

if ((l < 0L) || (l > 16777215L))

{

return null;

}

bytes[1] = (byte) (int) (l >> 16 & 0xFF);

bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);

bytes[3] = (byte) (int) (l & 0xFF);

break;

case 3:

for (i = 0; i < 2; ++i)

{

l = Integer.parseInt(elements[i]);

if ((l < 0L) || (l > 255L))

{

return null;

}

bytes[i] = (byte) (int) (l & 0xFF);

}

l = Integer.parseInt(elements[2]);

if ((l < 0L) || (l > 65535L))

{

return null;

}

bytes[2] = (byte) (int) (l >> 8 & 0xFF);

bytes[3] = (byte) (int) (l & 0xFF);

break;

case 4:

for (i = 0; i < 4; ++i)

{

l = Integer.parseInt(elements[i]);

if ((l < 0L) || (l > 255L))

{

return null;

}

bytes[i] = (byte) (int) (l & 0xFF);

}

break;

default:

return null;

}

}

catch (NumberFormatException e)

{

return null;

}

return bytes;

}

/**

  • 获取IP地址

  • @return 本地IP地址

/**

  • 获取主机名

  • @return 本地主机名

/**

  • 从多级反向代理中获得第一个非unknown IP地址

  • @param ip 获得的IP地址
  • @return 第一个非unknown IP地址

/**

  • 检测给定字符串是否为未知,多用于检测HTTP请求相关

  • @param checkString 被检测的字符串
  • @return 是否未知

1、没有代理

如果只是普通的web项目的话,通过 request.getRemoteAddr(); (HttpServletRequest 类型) 即可获取到客户端的真实IP

2、Nginx代理

在有代理的情况下,由于任何请求首先经过Nginx,故通过request.getRemoteAddr()获取的其实是Nginx的IP,并非真实的客户端IP;此时通过x-forwarded-for获取的IP为:"客户端,代理1,代理2,..."或者"伪造IP,客户端,代理1,代理2,...",故不能获取到准确的客户端IP,此时需要配置Nginx TCP客户端连接的真实IP,通过代理配置获取真实IP,可以通过$remote_addr获取客户端IP,Nginx配置如下:

location / {

//追加如下代码

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}