Build Zuul custom filters to limit frequent IP requests

Customizing zuul filters is actually quite simple

1. First poM files need to introduce zuul dependencies

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
Copy the code

2. Create a class that extends from ZuulFilter

import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.exception.ZuulException; import org.springframework.stereotype.Component; /** * Builds zuul custom filters */ @Component Public Class MyFilter extends ZuulFilter {/** * Defines the type of filter * pre: executes before the request is routed * * * @return filterType */ @override public String filterType() {route: executed when routing requests * post: executed after routing requests * error: executed when processing requests return "pre"; } @override public int filterOrder() {return 1;} @override public int filterOrder(); } @override public Boolean shouldFilter() {return true; } /** * Service implementation of the filter ** @return NULL is meaningless * @throws exception information */ @override public Object run() throws ZuulException { System.out.println("per zuul filter..." ); return null; }}Copy the code

This is required for custom classes@Componentannotations

The a.filterType () method, which defines the type of the filter, returns a string of four types

  • Pre: executed before the request is routed
  • Route: Executed when routing requests
  • Post: the request route is executed later
  • Error: Executed when an error occurs while processing a request

B. The filterOrder() method, the order in which filters are executed

C. ShouldFilter () : shouldFilter()

The d.run () method, the business implementation of the filter, writes the concrete code that implements the logic here

3. Limit IP frequent requests, sample code

import com.imooc.grace.result.GraceJsonResult; import com.imooc.grace.result.ResponseStatusEnum; import com.imooc.utils.IPUtil; import com.imooc.utils.JsonUtils; import com.imooc.utils.RedisOperator; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @component Public class BlackIpFilter extends ZuulFilter {/** * Private static final int  CONTINUE_COUNTS = 10; Private static final int TIME_INTERVAL = 10; private static final int TIME_INTERVAL = 10; Private static final int LIMIT_TIMES = 15; private static final int LIMIT_TIMES = 15; @Autowired private RedisOperator redisOperator; @Override public String filterType() { return "pre"; } @override public int filterOrder() {Override public int filterOrder(); } @Override public boolean shouldFilter() { return true; } @override public Object run() throws ZuulException {RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); // Get IP String requestIp = iputil. getRequestIp(request); Final String ipRedisKey = "zuul-ip:" + requestIp; final String ipRedisKey = "zuul-ip:" + requestIp; final String ipRedisKey = "zuul-ip:" + requestIp; final String ipRedisLimitKey = "zuul-ip-limit:" + requestIp; Long limitLeftTime = redisoperator. TTL (ipRedisLimitKey); If (limitLeftTime > 0) {stopRequest(currentContext); return null; } long requestCounts = redisOperator.increment(ipRedisKey, 1); if (requestCounts == 1) { redisOperator.expire(ipRedisKey, TIME_INTERVAL); } if (requestCounts > CONTINUE_COUNTS) {// Disoperator. set(ipRedisLimitKey, ipRedisLimitKey, LIMIT_TIMES); stopRequest(currentContext); } return null; {} private void stopRequest (RequestContext context) / / stop zuul continue down routing, inhibit communication request context. SetSendZuulResponse (false); / / returns a response code 200 context. SetResponseStatusCode (200); {"status":544," MSG ":" Requests are too frequent, ","success":false,"data":null} String result = "json content "; Context.setresponsebody (result); // Set the encoding context.getresponse ().setCharacterEncoding(" utF-8 "); // Set the format of the returned content to json context.getresponse ().setContentType(MediaType.APPLICATION_JSON_VALUE); }}Copy the code

Redis is used to record the number of IP requests and control the time interval

Get the IP utility class IPUtil

import javax.servlet.http.HttpServletRequest; Public class IPUtil {/** * obtain the requested IP address: * Request.getremoteaddr () cannot be used for the user's real IP address * This is because some proxy software may be used, so that the IP address is not accurate * If we use a multi-level (LVS/Nginx) reverse proxy, The IP address is valid only if the first non-unknown IP address is forwarded-for from x-Forwarded-for. */ public static String getRequestIp(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; }}Copy the code