`
eimhee
  • 浏览: 2112560 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 实现IP访问量控制

阅读更多

同一个IP 访问网站, 不能同时超过配置的最大值, 可以用来保护REST IP 或者DOS攻击

 

/*
 * Pprun's Public Domain.
 */
package org.pprun.common.security;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.scheduling.annotation.Scheduled;

/**
 * A filter to throttle only a limited number of requests from the same ip per second.
 * <p>
 * Two parameters need to inject:
 * <ol>
 * <li>common.throttle.maxConcurrentRequests=10</li>
 * <li>common.throttle.period=1000</li>
 * </ol>
 * <br />
 * If you use {@literal Spring} for {@lit DI}, it can be done as below in application {@literal web.xml}:
 * <br />
 * {@code 
 *      <filter>  
 *          <description>A filter to throttle only a limited number of requests from the same ip per second.</description>  
 *          <filter-name>throttleFilter</filter-name>  
 *          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
 *      </filter>
 * }
 * <br />
 * And a bean with {@code id="throttleFilter"} should be defined in {@literal application.xml}.
 * </p>
 * @author <a href="mailto:pizhigang@letv.com">pizhigang</a>
 */
//@Component
public class ThrottleFilter implements Filter, ThrottleFilterMXBean {

    private static Logger log = LoggerFactory.getLogger(ThrottleFilter.class);
    // map(ip, requestCount)
    private Map<String, Integer> ip2countCache = new HashMap<String, Integer>();
    private Set<String> blackList = new HashSet<String>();
    private int maxConcurrentRequests;
    private static final long PERIOD = 1L; // second
    private boolean enable = false;

    @Override
    public void init(FilterConfig config) throws ServletException {
        // nothing
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain nextFilter) throws ServletException, IOException {
        if (enable) {
            final String ip = request.getRemoteAddr();
            boolean isOverflow;

            synchronized (this) {
                Integer count = ip2countCache.get(ip);

                if (count == null || count.intValue() == 0) {
                    count = 0;
                }

                if (count < maxConcurrentRequests) {
                    isOverflow = false;
                    ip2countCache.put(ip, count + 1);
                } else {
                    isOverflow = true;
                    blackList.add(ip);
                }
            }

            if (isOverflow) {
                // block it
                log.info(" ip {} has reached the threshold {} in {} second, block it!", new Object[]{ip, maxConcurrentRequests, PERIOD});

                if (response instanceof HttpServletResponse) {
                    ((HttpServletResponse) response).sendError(503, ip + " has too many concurrent requests per " + PERIOD + " second");
                }
                return;
            }
        } // else go ahead below

        // every thing is okay, go ahead
        nextFilter.doFilter(request, response);
    }

    // every 1 second
    @Scheduled(fixedRate = PERIOD * 1000)
    public void throttlingJob() {
        if (enable) {
            log.debug("Throttle Filter clean up job is running");
            synchronized (ThrottleFilter.this) {
                for (Map.Entry<String, Integer> ip2count : ip2countCache.entrySet()) {
                    Integer count = ip2count.getValue();
                    String ip = ip2count.getKey();

                    if (count == null || count <= 1) {
                        ip2countCache.remove(ip);
                    } else {
                        if (count == maxConcurrentRequests) {
                            // remove from blacklist
                            log.info("Throttle Filter: removing {} from black list", ip);
                            blackList.remove(ip);
                        }

                        ip2countCache.put(ip, count - 1);
                    }
                }
            }
            log.debug("Throttle Filter clean up job is done");
        }
    }

    /**
     * Any cleanup for the filter.
     */
    @Override
    public void destroy() {
        log.warn("destorying Throttle Filter");
    }

    /**
     * Sets the maximum number of concurrent requests for a single IP.
     */
    @Required
    public void setMaxConcurrentRequests(int max) {
        maxConcurrentRequests = max;
    }

    @ManagedAttribute(description = "is the throttle filter enable or not")
    @Override
    public boolean isEnable() {
        return enable;
    }

    @Required
    @Override
    public void setEnable(boolean enable) {
        log.info("set enable to {}", enable);
        if (enable == false) {
            log.info("Throttle filter will be disabled");
        }

        this.enable = enable;
    }

    public Set<String> getBlackList() {
        // for exactly, it might need synchronized, but no hurt for snapshoot in one or severl seconds
        return Collections.unmodifiableSet(blackList);
    }
}

 

0
2
分享到:
评论

相关推荐

    java ip匹配 访问量+1

    java ip匹配 访问量+1 从 `IP地址文件` 中读取地址关系到自己的数据结构中; 2. 从 `日志文件` 中读取ip,解析关联的城市,对应的城市访问量 `+1` ; 3. 统计访问量最多的前10城市

    JAVA 统计网站的访问量PV,UV

    Java+Spring+Mysql+C3P0 统计网站的访问量,比如PV(页面浏览量),UV(独立访客数),将统计结果保存到MYSQL数据库中。解压后有项目log和Mysql的建库脚本。

    Java采集最新动态代理IP

    Jsoup实现代理IP的爬取,突破IP的访问限制,实现动态IP代理

    java源码包---java 源码 大量 实例

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    融成Java后台网站内容管理系统 v3.2.1.rar

    11.实时数据模块可以查看某一访客的访客IP、访客位置、入站来源信息、页面访问情况、当前状态、访客系统版本、浏览器版本、访客的点击收藏关注行为等多种信息; 12.访客分析可以查看访客的来源地区及占比情况等信息...

    java开源包4

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    JAVA上百实例源码以及开源项目源代码

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    用IP统计网站流量(java)

    利用IP统计网站的流量源码,当前在线人数,总访问量,总的页面访问量。网站制作必备

    JAVA上百实例源码以及开源项目

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    Java源码包100个设计实例.zip

    Java源码包100个设计实例, 大量 实例,可以...Java访问权限控制源代码.rar Java读写文本文件的示例代码 Java赌神游戏网络版源代码.rar Java超市管理,SQL2000+源代码.rar Java超市进销存系统.rar Java软件度量源码.ra

    java源码包4

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    java源码包3

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    java开源包3

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java包与接口实验报告

    3)网络包(java.net):支持Internet的TCP/IP协议,用于实现Socket编程;提供了与Internet的接口,支持URL连接,WWW的即时访问,并且简化了用户/服务器模型的程序设计。 4)抽象图形用户接口包(javax.swing):实现了...

    java源码包2

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    java开源包11

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包6

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包9

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包101

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    Java开发技术大全(500个源代码).

    signByIF.java 用if语句实现符号函数示例 triangleStar.java 输出一个由*组成的直角三角形 upperToLowCase.java 大写转换成小写 variableScopeExample.java 变量使用范围示例 第3章 示例描述:本章学习对象和类...

Global site tag (gtag.js) - Google Analytics