HttpServletRequest, ServerHttpRequest obtain the real IP of the visitor, and set the ip whitelist

When the project logs and the gateway processes the IP whitelist, the user IP is usually obtained, and the real IP of the visitor is usually obtained from HttpServletRequest and ServerHttpRequest
1. Obtain from HttpServletRequest (in the case of log printing):
public static String getIpAddr(HttpServletRequest request){
    
    
        String ip = null;

        // X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses))
        {
    
    
            // Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses))
        {
    
    
            // WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses))
        {
    
    
            // HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses))
        {
    
    
            // X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }

        // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0)
        {
    
    
            ip = ipAddresses.split(",")[0];
        }

        // 还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses))
        {
    
    
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
2. (SpringCloud-Gateway second-generation gateway) obtained from ServerHttpRequest
public static String getIpAddress(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.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
How to filter the whitelist after obtaining the IP
package com.maorong.gateway.config.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

/**
 * 从nacos获取IP白名单配置信息
 *
 * @author sk
 * @DATE: 2021/5/12
 */
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "whiteip")
public class WhiteIpListProperties
{
    
    
    /**
     * 放行IP白名单配置,网关不校验此处的IP白名单
     */
    private List<String> whites = new ArrayList<>();

    public List<String> getWhites()
    {
    
    
        return whites;
    }

    public void setWhites(List<String> whites)
    {
    
    
        this.whites = whites;
    }
}

Nacos configuration information:

Gateway add filter Filter
/**
 * 网关鉴权
 * @author sk
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered
{
    
    
    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);

    private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;

    // 排除过滤的 ip,nacos自行添加
    @Autowired
    private WhiteIpListProperties WhiteIp;
	
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
    
    
        // 跳过不需要验证的 ip白名单
        String reqIp = IPUtils.getIpAddress(exchange.getRequest());
        log.info("<<<<<<<请求的reqIp:"+reqIp);
        if (!StringUtils.matches(reqIp, WhiteIp.getWhites()))
        {
    
    
            return setUnauthorizedResponse(exchange, "没有权限访问!");
        }
        
    }
Determine whether the ip whitelist has been configured
public class StringUtils extends org.apache.commons.lang3.StringUtils{
    
    
/**
     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
     *
     * @param str 指定字符串
     * @param strs 需要检查的字符串数组
     * @return 是否匹配
     */
    public static boolean matches(String str, List<String> strs)
    {
    
    
        if (isEmpty(str) || isEmpty(strs))
        {
    
    
            return false;
        }
        for (String testStr : strs)
        {
    
    
            if (matches(str, testStr))
            {
    
    
                return true;
            }
        }
        return false;
    }

    /**
     * 查找指定字符串是否匹配指定字符串数组中的任意一个字符串
     *
     * @param str 指定字符串
     * @param strs 需要检查的字符串数组
     * @return 是否匹配
     */
    public static boolean matches(String str, String... strs)
    {
    
    
        if (isEmpty(str) || isEmpty(strs))
        {
    
    
            return false;
        }
        for (String testStr : strs)
        {
    
    
            if (matches(str, testStr))
            {
    
    
                return true;
            }
        }
        return false;
    }

    /**
     * 查找指定字符串是否匹配
     *
     * @param str 指定字符串
     * @param pattern 需要检查的字符串
     * @return 是否匹配
     */
    public static boolean matches(String str, String pattern)
    {
    
    
        if (isEmpty(pattern) || isEmpty(str))
        {
    
    
            return false;
        }

        pattern = pattern.replaceAll("\\s*", ""); // 替换空格
        int beginOffset = 0; // pattern截取开始位置
        int formerStarOffset = -1; // 前星号的偏移位置
        int latterStarOffset = -1; // 后星号的偏移位置

        String remainingURI = str;
        String prefixPattern = "";
        String suffixPattern = "";

        boolean result = false;
        do
        {
    
    
            formerStarOffset = indexOf(pattern, START, beginOffset);
            prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());

            // 匹配前缀Pattern
            result = remainingURI.contains(prefixPattern);
            // 已经没有星号,直接返回
            if (formerStarOffset == -1)
            {
    
    
                return result;
            }

            // 匹配失败,直接返回
            if (!result)
                return false;

            if (!isEmpty(prefixPattern))
            {
    
    
                remainingURI = substringAfter(str, prefixPattern);
            }

            // 匹配后缀Pattern
            latterStarOffset = indexOf(pattern, START, formerStarOffset + 1);
            suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());

            result = remainingURI.contains(suffixPattern);
            // 匹配失败,直接返回
            if (!result)
                return false;

            if (!isEmpty(suffixPattern))
            {
    
    
                remainingURI = substringAfter(str, suffixPattern);
            }

            // 移动指针
            beginOffset = latterStarOffset + 1;

        }
        while (!isEmpty(suffixPattern) && !isEmpty(remainingURI));

        return true;
    }

    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj)
    {
    
    
        return (T) obj;
    }


/**
     * * 判断一个字符串是否为空串
     *
     * @param str String
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(String str)
    {
    
    
        return isNull(str) || NULLSTR.equals(str.trim());
    }

}

Guess you like

Origin blog.csdn.net/SHUKAI618/article/details/116719462