美文网首页
HttpServletRequest、ServerHttpReq

HttpServletRequest、ServerHttpReq

作者: 划水的鱼仔 | 来源:发表于2021-05-12 19:32 被阅读0次
    在项目记录日志的时候和网关处理IP白名单的时候,通常会获取用户IP,一般都会从HttpServletRequest、ServerHttpRequest获取访问者真实IP
    1.从HttpServletRequest中获取(日志打印的情况):
    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二代网关)从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;
        }
    
    获取到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配置信息:
    image
    网关添加过滤器 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, "没有权限访问!");
            }
            
        }
    
    判断是否配置过ip白名单
    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());
        }
    
    }
    

    相关文章

      网友评论

          本文标题:HttpServletRequest、ServerHttpReq

          本文链接:https://www.haomeiwen.com/subject/alfzdltx.html