首頁>技術>

編寫一個過濾器:

package org.jeemp.config;import java.io.IOException;import java.util.Iterator;import java.util.Map;import java.util.Set;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.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.jeemp.utils.IpUtils;/** * @author JackRen * @date 2021-02-27 14:51 * @description: * 自定義過濾器,用來判斷IP訪問次數是否超限 *  如果前臺使用者訪問網站的頻率過快(達到超過50次/秒),則判定該ip惡意重新整理操作, * 限制該IP的訪問,1小時後自己解除限制 */@WebFilter(urlPatterns="/*")public class IpFilter implements Filter {    /**     * 預設限制時間(單位:ms)     */    private static final long LIMITED_TIME_MILLIS = 60 * 60 * 1000;    /**     * 使用者連續訪問最高閥值,超過該值則認定為惡意操作的IP,進行限制     */    private static final int LIMIT_NUMBER = 50;    /**     * 使用者訪問最小安全時間,在該時間內如果訪問次數大於閥值,則記錄為惡意IP,否則視為正常訪問     */    private static final int MIN_SAFE_TIME = 5000;    private FilterConfig config;    @Override    public void init(FilterConfig filterConfig) throws ServletException {        this.config = filterConfig;    //設定屬性filterConfig    }    /* (non-Javadoc)     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)     */    @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儲存器:儲存被限制的IP資訊        Map<String, Long> limitedIpMap = (Map<String, Long>) context.getAttribute("limitedIpMap");        // 過濾受限的IP        filterLimitedIpMap(limitedIpMap);        // 獲取使用者IP        String ip = IpUtils.getRemoteHost(request);        System.err.println("ip:"+ip);        // 判斷是否是被限制的IP,如果是則跳到異常頁面        if (isLimitedIP(limitedIpMap, ip)) {            long limitedTime = limitedIpMap.get(ip) - System.currentTimeMillis();            // 剩餘限制時間(用為從毫秒到秒轉化的一定會存在些許誤差,但基本可以忽略不計)            request.setAttribute("remainingTime", ((limitedTime / 1000) + (limitedTime % 1000 > 0 ? 1 : 0)));            //request.getRequestDispatcher("/error/overLimitIP").forward(request, response);            System.err.println("ip訪問過於頻繁:"+ip);            //response.setCharacterEncoding("gb2312");    //設定輸出內容編碼格式//            response.reset();//            response.setCharacterEncoding("utf-8");    //設定輸出內容編碼格式//            PrintWriter out = response.getWriter();//            out.println("<b>由於您訪問過於頻繁,被系統自動認定為機器人。1個小時自動解除</b>");、            return;        }        // 獲取IP儲存器        Map<String, Long[]> ipMap = (Map<String, Long[]>) context.getAttribute("ipMap");        // 判斷儲存器中是否存在當前IP,如果沒有則為初次訪問,初始化該ip        // 如果存在當前ip,則驗證當前ip的訪問次數        // 如果大於限制閥值,判斷達到閥值的時間,如果不大於[使用者訪問最小安全時間]則視為惡意訪問,跳轉到異常頁面        if (ipMap.containsKey(ip)) {            Long[] ipInfo = ipMap.get(ip);            ipInfo[0] = ipInfo[0] + 1;            System.out.println("當前第[" + (ipInfo[0]) + "]次訪問");            if (ipInfo[0] > LIMIT_NUMBER) {                Long ipAccessTime = ipInfo[1];                Long currentTimeMillis = System.currentTimeMillis();                if (currentTimeMillis - ipAccessTime <= MIN_SAFE_TIME) {                    limitedIpMap.put(ip, currentTimeMillis + LIMITED_TIME_MILLIS);                    request.setAttribute("remainingTime", LIMITED_TIME_MILLIS);                    System.err.println("ip訪問過於頻繁:"+ip);                    request.getRequestDispatcher("/error/overLimitIP").forward(request, response);                    return;                } else {                    initIpVisitsNumber(ipMap, ip);                }            }        } else {            initIpVisitsNumber(ipMap, ip);            System.out.println("您首次訪問該網站");        }        context.setAttribute("ipMap", ipMap);        chain.doFilter(request, response);    }    @Override    public void destroy() {        // TODO Auto-generated method stub    }    /**     * @Description 過濾受限的IP,剔除已經到期的限制IP     * @param limitedIpMap     */    private void filterLimitedIpMap(Map<String, Long> limitedIpMap) {        if (limitedIpMap == null) {            return;        }        Set<String> keys = limitedIpMap.keySet();        Iterator<String> keyIt = keys.iterator();        long currentTimeMillis = System.currentTimeMillis();        while (keyIt.hasNext()) {            long expireTimeMillis = limitedIpMap.get(keyIt.next());            if (expireTimeMillis <= currentTimeMillis) {                keyIt.remove();            }        }    }    /**     * @Description 是否是被限制的IP     * @param limitedIpMap     * @param ip     * @return true : 被限制 | false : 正常     */    private boolean isLimitedIP(Map<String, Long> limitedIpMap, String ip) {        if (limitedIpMap == null || ip == null) {            // 沒有被限制            return false;        }        Set<String> keys = limitedIpMap.keySet();        Iterator<String> keyIt = keys.iterator();        while (keyIt.hasNext()) {            String key = keyIt.next();            if (key.equals(ip)) {                // 被限制的IP                return true;            }        }        return false;    }    /**     * 初始化使用者訪問次數和訪問時間     *     * @param ipMap     * @param ip     */    private void initIpVisitsNumber(Map<String, Long[]> ipMap, String ip) {        Long[] ipInfo = new Long[2];        ipInfo[0] = 0L;// 訪問次數        ipInfo[1] = System.currentTimeMillis();// 初次訪問時間        ipMap.put(ip, ipInfo);    }}
建立一個監聽器:需要初始化兩個容器
package org.jeemp.config;import java.util.HashMap;import java.util.Map;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.annotation.WebListener;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * @author JackRen * @date 2021-02-27 14:56 * @description: */public class MyListener implements ServletContextListener{    private Logger logger =  LoggerFactory.getLogger(MyListener.class);    @Override    public void contextInitialized(ServletContextEvent sce) {        logger.info("liting: contextInitialized");        System.err.println("MyListener初始化成功");        ServletContext context = sce.getServletContext();        // IP儲存器        Map<String, Long[]> ipMap = new HashMap<String, Long[]>();        context.setAttribute("ipMap", ipMap);        // 限制IP儲存器:儲存被限制的IP資訊        Map<String, Long> limitedIpMap = new HashMap<String, Long>();        context.setAttribute("limitedIpMap", limitedIpMap);        logger.info("ipmap:"+ipMap.toString()+";limitedIpMap:"+limitedIpMap.toString()+"初始化成功。。。。。");    }    @Override    public void contextDestroyed(ServletContextEvent sce) {        // TODO Auto-generated method stub    }}
啟動類裡面新增以上監聽器和過濾器的掃描包路徑
@ServletComponentScan(basePackages="org.jeemp")

6
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 單鏈表(Singly Linked List)的實現