• 黑名单设计


    目标:实现黑名单机制,防止网络游戏爬虫

    public class BlackListFilter implements Filter, ApplicationContextAware {
        private final static Logger LOG = LoggerFactory.getLogger(BlackListFilter.class);
    
        private WConfigService wConfigService;
    
        private JedisClient jedisClient;
    
        private static Map<String, Integer> queue = Maps.newConcurrentMap();
    
        private final static String WISH_LIST_BLACK_LIST_CACHE = "wish_list_black_list_cache";
    
        private final static int EXPIRE_TIME = 24 * 60 * 60;
    
        private final static String UN_KNOW = "unknown";
    
        private final static String WCONFIG_NAME = "wConfigService";
    
        private final static String JEDIS_NAME = "jedisClient";
    
        private static ApplicationContext ctx;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        private void init() {
            if (ctx != null && ctx.getBean(WCONFIG_NAME) != null && wConfigService == null) {
                wConfigService = (WConfigService) ctx.getBean(WCONFIG_NAME);
            }
            if (ctx != null && ctx.getBean(JEDIS_NAME) != null && jedisClient == null) {
                jedisClient = (JedisClient) ctx.getBean(JEDIS_NAME);
            }
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            //防止NPE
            if (Objects.isNull(wConfigService)
                    || Objects.isNull(jedisClient)) {
                init();
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            //开关关闭
            if (!wConfigService.obtainBlackListIsWork()) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            try {
                String ip = getIp(servletRequest);
                if (StringUtils.isBlank(ip)) {
                    LOG.error("没有找到客户端ip");
                    filterChain.doFilter(servletRequest, servletResponse);
                    return;
                }
                //判断是否在黑名单内
                String blackListCache = Objects.nonNull(jedisClient.get(WISH_LIST_BLACK_LIST_CACHE))
                        ? jedisClient.get(WISH_LIST_BLACK_LIST_CACHE)
                        : "";
                List<String> blackList = CollectionUtils.isNotEmpty(JsonUtil.ofList(blackListCache, String.class))
                        ? JsonUtil.ofList(blackListCache, String.class)
                        : Lists.newArrayList();
                if (blackList.contains(ip)) {
                    LOG.info("系统拒绝ip:" + ip + "的访问!");
                    throw new IllegalArgumentException();
                }
                int count = 0;
                if (queue.keySet().contains(ip)) {
                    count = queue.get(ip);
                    count++;
                    queue.put(ip, count);
                }
                else {
                    count++;
                    queue.put(ip, count);
                }
                int limitCount = Integer.valueOf(wConfigService.obtainBlackListLimitCount());
                if (count >= limitCount) {
                    synchronized (this) {
                        queue.remove(ip);
                        //超过访问次数限制,加入黑名单
                        if (CollectionUtils.isEmpty(blackList)) {
                            //清除昨天的历史记录
                            queue = Maps.newConcurrentMap();
                            //第一次加入黑名单
                            blackList = Lists.newArrayList();
                            blackList.add(ip);
                            jedisClient.set(WISH_LIST_BLACK_LIST_CACHE, JsonUtil.toJson(blackList));
                            jedisClient.expire(WISH_LIST_BLACK_LIST_CACHE, EXPIRE_TIME);
                        }
                        else {
                            //黑名单增加ip
                            blackList.add(ip);
                            jedisClient.set(WISH_LIST_BLACK_LIST_CACHE, JsonUtil.toJson(blackList));
                        }
                        filterChain.doFilter(servletRequest, servletResponse);
                    }
                }
                else {
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            }
            catch (IllegalArgumentException e) {
                throw new IllegalArgumentException("今天的心愿太多了,请明天再来吧!");
            }
            catch (Exception e) {
                LOG.error("黑名单过滤数据异常");
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    
        private String getIp(ServletRequest servletRequest) {
            String ip = "";
            try {
                if (servletRequest instanceof HttpServletRequest) {
                    HttpServletRequest request = (HttpServletRequest) servletRequest;
                    String ipAddresses = request.getHeader("x-forwarded-for");
                    if (ipAddresses == null || ipAddresses.length() == 0 || UN_KNOW.equalsIgnoreCase(ipAddresses)) {
                        //Proxy-Client-IP:apache 服务代理
                        ipAddresses = request.getHeader("Proxy-Client-IP");
                    }
                    if (ipAddresses == null || ipAddresses.length() == 0 || UN_KNOW.equalsIgnoreCase(ipAddresses)) {
                        //WL-Proxy-Client-IP:weblogic 服务代理
                        ipAddresses = request.getHeader("WL-Proxy-Client-IP");
                    }
                    if (ipAddresses == null || ipAddresses.length() == 0 || UN_KNOW.equalsIgnoreCase(ipAddresses)) {
                        //HTTP_CLIENT_IP:有些代理服务器
                        ipAddresses = request.getHeader("HTTP_CLIENT_IP");
                    }
                    if (ipAddresses == null || ipAddresses.length() == 0 || UN_KNOW.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 || UN_KNOW.equalsIgnoreCase(ipAddresses)) {
                        ip = request.getRemoteAddr();
                    }
                }
            }
            catch (Exception e) {
                ip = "";
                LOG.info("获取ip失败,失败原因:" + e.getMessage());
            }
            return ip;
        }
    
        @Override
        public void destroy() {
    
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            BlackListFilter.ctx = applicationContext;
        }
    }
  • 相关阅读:
    java的初始化
    java继承
    java多态
    static、final关键字
    java的清理
    java访问权限控制
    java对象与引用及参数传递
    java学习--学生成绩管理系统
    The Nth Item 南昌网络赛(递推数列,分段打表)
    Random Access Iterator 徐州网络赛(树形dp)
  • 原文地址:https://www.cnblogs.com/zhangchiblog/p/10907497.html
Copyright © 2020-2023  润新知