java拦截ip和限制ip访问接口的次数

转载请标明出处:
https://blog.youkuaiyun.com/weixin_41965979/article/details/90720405
本文出自付付讶的博客

          这两天因为公司需求需要加一个限制ip请求次数的功能,限制某些ip一天只能访问10次,现在总结一下(因为是老项目所以用的是servlet)

用到的jar包:commons-lang3-3.8.1.jar

用到的技术:过滤器(Filter)

思路:数据库里创建2字段,一个ip,一个请求次数,并给他们填上值:ip写上你要拦截的ip,次数全部填0;

           代码里创建一个Map,用来存放要拦截的ip地址,通过反向代理得到当前请求的ip,拿到ip查询当前次数,然后判断Map             里包不包括当前请求的Ip地址,有的话则计算请求次数,然后在数据库里添加一个定时器每天0点清空次数                (https://blog.youkuaiyun.com/weixin_41965979/article/details/90700370这篇文章有写数据库怎么添加一个自动定时器),这样的话次数都是当天的,最后判断次数大于10就给它跳错误页面就行了;

下面直接上代码,有问题可以留言交流;

配置文件(web.xml): 

 <!-- 配置过滤器-->  
    <filter>  
       <filter-name>IPFilter</filter-name>  
       <filter-class>com.roadLeader.filter.IPFilter</filter-class>  
    </filter>  
    <filter-mapping>  
       <filter-name>IPFilter</filter-name>  
       <url-pattern>/*</url-pattern>  
    </filter-mapping>  

 新建一个过滤器类(IPFilter):

import java.io.IOException;  
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;  
import java.util.Map.Entry;
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import org.apache.commons.lang3.StringUtils;
import com.roadLeader.jdbc.LinkDB;
/** 
 * @Description 自定义过滤器,用来判断IP访问次数是否超限。<br> 
 * @author fling 
 * @date 2019年5月28日 
 * @since JDK : 1.7 
 */  
public class IPFilter implements Filter{

    private FilterConfig config;  
     
    //统计ip请求次数
      int count;
      Integer	numbers;
      //存储ip
      Map<String, Integer> ipMap=new HashMap<String, Integer>();
    @Override  
    public void init(FilterConfig filterConfig) throws ServletException {  
        this.config = filterConfig; 

       //以下是我要拦截的ip(由于工作业务原因,不方便展示真实ip,以下全部用127.0.0.1代替,实际上 
                          是5个不同的客户的ip,此ip跟数据库要对上哟)
        ipMap.put("127.0.0.1", count);
        ipMap.put("127.0.0.1", count);
        ipMap.put("127.0.0.1", count);
        ipMap.put("127.0.0.1", count);
        ipMap.put("127.0.0.1", count);
    }  
  
    /** 
     * @Description 核心处理代码 
     */  
    @SuppressWarnings("unchecked")  
    @Override  
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)  
            throws IOException, ServletException {  
        HttpServletRequest request = (HttpServletRequest) servletRequest;  
        HttpServletResponse response = (HttpServletResponse) servletResponse; 
        ServletContext context = config.getServletContext(); 

      //得到当前请求的ip
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnow".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值,第一个ip才是真实ip
            String[] ipList1 = ip.split(",");
            ip = ipList1[0];
         } else {
            ip = request.getHeader("X-Real-IP");
            if (StringUtils.isEmpty(ip) || "unKnown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
         }

       //查询ip和次数
        String aliIp="";
        int number=0;
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			Connection conn = new LinkDB().getConnection();
			String sql = "SELECT number,ip FROM ipTable  WHERE ip='"+ip+"'";
			PreparedStatement pre = conn.prepareStatement(sql);
			ResultSet rs = pre.executeQuery(); 				
			while (rs.next()) {
				 aliIp = rs.getString("ip");
				 number = rs.getInt("number");
			};
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

        //判断如果包括当前请求ip则计算请求次数
        if(ipMap.containsKey(ip)){
        	numbers = number+1;
        	try {
    			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    			Connection conn = new LinkDB().getConnection();
    			String sql = "update ipTable set  number=? where ip=?";
    			PreparedStatement pre = conn.prepareStatement(sql);
    			pre.setInt(1, numbers);
    			pre.setString(2, ip);
    			pre.executeUpdate();
    			conn.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
        }else{
        	ipMap.put(ip, 1);
        }
        context.setAttribute("ipMap", ipMap);  
        chain.doFilter(request, response);

        //判断大于10次跳错误页面
        if(numbers>10){
       	 request.getRequestDispatcher("WEB-INF/error.jsp").forward(request, response);
       
       }
        
    }
    @Override  
    public void destroy() {  
    } 
}

测试:

      当我发送第一次请求时,数据库次数变成了1,这时应该响应成功(数据私密性这里打上马赛克);

当我发送到第11次请求时 ,这时候数据库次数变成11,响应返回报错页面;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值