From 089bb1f584cc8adf189bfd32ac089a11dc982a7a Mon Sep 17 00:00:00 2001 From: lzy <1768422698@qq.com> Date: Tue, 17 Dec 2024 21:16:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yami/shop/common/util/IpHelper.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 yami-shop-common/src/main/java/com/yami/shop/common/util/IpHelper.java diff --git a/yami-shop-common/src/main/java/com/yami/shop/common/util/IpHelper.java b/yami-shop-common/src/main/java/com/yami/shop/common/util/IpHelper.java new file mode 100644 index 0000000..37e22c8 --- /dev/null +++ b/yami-shop-common/src/main/java/com/yami/shop/common/util/IpHelper.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved. + * + * https://www.mall4j.com/ + * + * 未经允许,不可做商业用途! + * + * 版权所有,侵权必究! + */ + +package com.yami.shop.common.util; + +// 导入Servlet相关的用于操作HTTP请求的类,后续用于获取请求头以及客户端IP地址等信息 +import jakarta.servlet.http.HttpServletRequest; + +/** + * IpHelper类是一个工具类,主要用于获取客户端(用户)的真实IP地址。 + * 在网络环境中,由于可能存在代理服务器等情况,获取IP地址的方式会有所不同, + * 该类通过依次检查不同的请求头信息以及直接获取远程地址的方式来尝试获取客户端真实IP地址, + * 并且如果获取到多个IP地址(例如经过多层代理的情况),则取第一个作为客户端的真实IP地址返回。 + * + * @author lanhai + */ +public class IpHelper { + + // 定义一个表示未知IP地址的常量字符串,用于后续判断请求头中获取到的IP地址是否有效 + private static final String UNKNOWN = "unknown"; + + /** + * 获取用户真实IP地址的方法,按照一定的顺序检查不同的请求头以及直接获取远程地址来确定客户端的IP地址。 + * 首先尝试从"x-forwarded-for"请求头获取IP地址,因为在经过代理服务器转发时,该请求头可能包含了客户端的真实IP地址; + * 如果该请求头获取到的IP地址为空、长度为0或者是表示未知的字符串("unknown"),则接着尝试从"Proxy-Client-IP"请求头获取; + * 若还是不符合要求,再尝试从"WL-Proxy-Client-IP"请求头获取; + * 若以上请求头都无法获取到有效IP地址,则直接获取请求的远程地址(RemoteAddr)作为IP地址; + * 最后,如果获取到的IP地址字符串包含多个IP(以逗号分隔,可能经过多层代理的情况),则取第一个IP作为最终的客户端真实IP地址返回。 + * + * @return String 返回获取到的客户端真实IP地址,如果由于各种原因无法获取到(例如没有有效的请求上下文等)则返回null + */ + public static String getIpAddr() { + // 通过HttpContextUtils工具类获取当前线程绑定的HttpServletRequest对象,该对象包含了请求相关的各种信息 + HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); + // 如果获取到的HttpServletRequest对象为null,说明无法获取到请求上下文相关信息,直接返回null,无法获取IP地址 + if (request == null) { + return null; + } + + // 首先尝试从"x-forwarded-for"请求头获取IP地址,该请求头在经过代理服务器转发时可能包含客户端真实IP + String ip = request.getHeader("x-forwarded-for"); + // 如果获取到的IP地址为空、长度为0或者等于表示未知的字符串(不区分大小写比较),则继续尝试从其他请求头获取 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + // 如果从"Proxy-Client-IP"请求头获取到的IP地址仍不符合要求(为空、长度为0或者是未知字符串),则再尝试从"WL-Proxy-Client-IP"请求头获取 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + // 如果经过前面的尝试还是没有获取到有效IP地址,则直接获取请求的远程地址(RemoteAddr)作为IP地址,这是最基本的获取客户端IP的方式 + if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + // 将获取到的IP地址字符串按照逗号进行分割,因为可能存在经过多层代理,IP地址有多个的情况(以逗号分隔) + String[] ips = ip.split(","); + // 返回分割后的第一个IP地址(去除两端的空白字符)作为客户端的真实IP地址,如果只有一个IP则就是该IP本身 + return ips[0].trim(); + } +} \ No newline at end of file