本篇文章主要介紹了spring boot攔截器實作IP黑名單實例程式碼,具有一定的參考價值,有興趣的小夥伴們可以參考一下
前言
最近一直在搞Hexo+GithubPage 來建立個人博客,所以沒怎麼進行SpringBoot 的學習。所以今天就將上次的”?秒防刷新”進行了一番修改。上次是採用註解加攔截器(@Aspect)來實現功能的。但是,如果需求是一個全局的攔截器對於大部分URL都進行攔截的話,自己一個個加顯然是不可能的。而且上次的攔截器對於Controller的參數有所要求,在實際他人引用總是顯得不方便。所以,這次使用了繼承HandlerInterceptor來實作攔截器。
功能需求
對於項目中某類URL進行攔截,若用戶在短時間內大量訪問該鏈接,則將用戶IP列入黑名單,禁止使用者造訪網頁。 (同時,可以使用@Async來建立定時任務幫使用者解禁。)
知識記錄
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 | |
iptime |
實體類別
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 方法 }
配置與對應實體配置(省略)。
@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"; }
以上是java實作IP黑名單的程式碼實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!