在 Java Web 应用中,想要在接口中获取到发送请求的客户端 IP 地址,需要依赖请求对象 —— HttpServletRequest。
那么,首先就是要先获取到请求的对象。
在 Spring Boot 中,只需在接口方法上加上 HttpServletRequest 或 HttpServletResponse 参数,Spring Boot 就会自动绑定这两个对象,然后可以直接使用。如果你的方法有其他参数,只需把这两个加到后面即可。例如:
@GetMapping("/getSomething")
public String getSomething(..., HttpServletRequest request, HttpServletResponse response) {
//...
}
这是最常用的一种方法,当然除了这种方式,在 Spring Boot 中还可以使用注解 @Autowired 注入或通过 RequestContextHolder 来获取请求对象,这里就不展开叙述了。
在得到请求对象 HttpServletRequest 对象后,一般的,我们可以使用 request.getRemoteAddr()
来获取到客户端对应的 IP 地址。
但是,如果使用了 Nginx 等反向代理软件,则不能只简单地通过上述代码来获取 IP;并且,如果使用了多级反向代理的话,那么在获取 X-Forwarded-For 的值时,得到的应是一串 IP 地址,此种情况下,X-Forwarded-For 中第一个非 unknown
的有效 IP 字符串,则为真实 IP 地址。
Talk is cheap, show me code.
下面是一个封装的工具类,用于从 HttpServletRequest 对象中获取相应的客户端 IP 地址。
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IpUtil {
private static final String UNKNOWN = "unknown";
private static final String LOCALHOST_IP = "127.0.0.1";
// 客户端与服务器同为一台机器,获取的 ip 有时候是 ipv6 格式
private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
private static final String SEPARATOR = ",";
// 根据 HttpServletRequest 获取 IP
public static String getIpAddress(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();
if (LOCALHOST_IP.equalsIgnoreCase(ip) || LOCALHOST_IPV6.equalsIgnoreCase(ip)) {
// 根据网卡取本机配置的 IP
InetAddress iNet = null;
try {
iNet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
if (iNet != null)
ip = iNet.getHostAddress();
}
}
// 对于通过多个代理的情况,分割出第一个 IP
if (ip != null && ip.length() > 15) {
if (ip.indexOf(SEPARATOR) > 0) {
ip = ip.substring(0, ip.indexOf(SEPARATOR));
}
}
return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IP : ip;
}
}