1. 程式人生 > >spring boot 學習(十二)攔截器實現IP黑名單

spring boot 學習(十二)攔截器實現IP黑名單

ppi html .html 日期類 dpa asp tails 我們 req

攔截器實現IP黑名單

前言

最近一直在搞 Hexo+GithubPage 搭建個人博客,所以沒怎麽進行 SpringBoot 的學習。所以今天就將上次的”?秒防刷新”進行了一番修改。上次是采用註解加攔截器(@Aspect)來實現功能的。但是,如果需求是一個全局的攔截器對於大部分URL都進行攔截的話,自己一個個加顯然是不可能的。而且上次的攔截器對於Controller的參數有所要求,在實際他人引用總是顯得不方便。所以,這次使用了繼承HandlerInterceptor來實現攔截器。

功能需求

對於項目中某類URL進行攔截,若用戶在短時間內大量訪問該鏈接,則將用戶IP列入黑名單,禁止用戶訪問網頁。(同時,可以使用@Async

來創建定時任務幫用戶解禁。)

準備

?秒防刷新的業務邏輯

博客地址 : http://blog.csdn.net/u011244202/article/details/54783337
項目參考地址 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B5

SpringBoot+Druid+MyBatis

博客地址 : http://blog.csdn.net/u011244202/article/details/54709060
項目參考地址 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B1

知識記錄

Spring 的攔截器 HandlerInterceptor 的功能跟過濾器類似,但是提供更精細的的控制能力:在request被響應之前、request被響應之後、視圖渲染之前以及request全部結束之後。我們不能通過攔截器修改request內容,但是可以通過拋出異常(或者返回false)來暫停request的執行。
配置攔截器也很簡單,Spring 為此提供了基礎類WebMvcConfigurerAdapter ,我們只需要重寫addInterceptors 方法添加註冊攔截器。

實現自定義攔截器只需要3步:
1、創建我們自己的攔截器類並實現 HandlerInterceptor 接口。
2、創建一個 Java 類繼承 WebMvcConfigurerAdapter,並重寫 addInterceptors 方法。
3、實例化我們自定義的攔截器,然後將對像手動添加到攔截器鏈中(在addInterceptors方法中添加)。

正式開工

IP工具類

由於不清楚用戶代理,最好能使用一個工具類來來獲取用戶真實IP。這個Google就能找到,我就不貼代碼了。

數據庫

我使用的是MySQL數據庫,持久層框架為MyBatis。具體可參考”準備”步驟。
我在”myboot”數據庫中創建一張表”blaclist”,屬性如下:

字段名解釋
id 記錄的id
ip 用戶真實IP
iptime IP被鎖時間

實體類

public class BlackList {

    private int id;
    private String ip;
    private Date iptime; // 日期類型,格式:yyyy-MM-dd HH:mm:ss
    //構造器
    public BlackList() {
    }

    public BlackList(String ip, Date iptime) {
        this.ip = ip;
        this.iptime = iptime;
    }
    // get && set 方法
}

Dao層

註意XML配置與對應實體配置(省略)。

@Mapper
public interface BlackListDao {
    // 根據IP來查找記錄
    List<BlackList> findByIp(String ip);
    // 添加記錄
    int addBlackList(@Param("blackList") BlackList blackList);
}

實現 HandlerInterceptor 接口

public class URLInterceptor implements HandlerInterceptor {

    @Autowired
    BlackListDao blackListDao;

    private Map<String, Integer> redisTemplate = new HashMap<String, Integer>();
    private static final Logger logger = LoggerFactory.getLogger(URLInterceptor.class);

    //在請求處理之前進行調用(Controller方法調用之前)
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        return true;
    }

    //請求處理之後進行調用,但是在視圖被渲染之前(Controller方法調用之後)
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        String ip = IPAddressUtil.getClientIpAddress(httpServletRequest);
        List<BlackList> blackLists = blackListDao.findByIp(ip);
        if (blackLists == null || blackLists.size() == 0){
            urlHandle(httpServletRequest, 5000, 10);
        } else {
            //強制控制跳轉
            modelAndView.setViewName("/errorpage/error.html");
        }
    }

    //在整個請求結束之後被調用
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    public void urlHandle(HttpServletRequest request, long limitTime,int limitCount) throws RequestLimitException {
            /**
             * 省略業務邏輯部分,參考"準備"步驟
             */
            if (count > limitCount){ //符合鎖定條件
                Calendar calendar = Calendar.getInstance();
                Date iptime=calendar.getTime();
                BlackList blackList = new BlackList(ip, iptime);
                blackListDao.addBlackList(blackList);
                throw new RequestLimitException();
            }
    }
}

WebMvcConfigurerAdapter類

配置 spring mvc的攔截器 WebMvcConfigurerAdapter。

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {

    @Bean   //把我們的攔截器註入為bean
    public HandlerInterceptor getMyInterceptor(){
        return new URLInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多個攔截器組成一個攔截器鏈
        // addPathPatterns 用於添加攔截規則, 這裏假設攔截 /url 後面的全部鏈接
        // excludePathPatterns 用戶排除攔截
        registry.addInterceptor(getMyInterceptor()).addPathPatterns("/url/**");
        super.addInterceptors(registry);
    }
}

Controller類

    @RequestMapping("/url/test")
    @ResponseBody
    public String URLtest() {
        return "success";
    }

spring boot 學習(十二)攔截器實現IP黑名單