According to?

The purpose of this article is to help websites limit the frequency of users’ visits, and to a certain extent block some crawler attacks. You can use the extension get_client_ID to identify the client or HTTP_FORBIDDEN to pass the verification code back and forth. Slider operation and other man-machine verification

Install OpenResty

OpenResty® effectively turns Nginx into a powerful general-purpose Web application platform by bringing together a variety of well-designed Nginx modules, mainly developed by the OpenResty team. In this way, Web developers and system engineers can use Lua scripting language to mobilize various C and Lua modules supported by Nginx, and quickly construct high-performance Web application systems that are competent for 10K or even 1000K stand-alone concurrent connections. OpenResty is an NginX-based platform that provides a number of high quality third-party modules. We use the combination of Redis + Lua this time, so we need OpenResty to provide lua environment. Click here to download

Create a new site for testing

package main
import "github.com/gofiber/fiber/v2"
func main(a) {
	app := fiber.New()

	app.Get("/".func(c *fiber.Ctx) error {
		return c.SendString("content content content")
	})

	app.Get("/api/member/get".func(c *fiber.Ctx) error {
		user := struct {
			UserName string `json:"userName"`
			Age      int    `json:"age"`
		}{UserName: "juejin", Age: 100}
		return c.JSON(user)
	})

	app.Listen(": 8080")}Copy the code

In the above code, we provide an HTTP GET/API /member/get API, which returns a bunch of JSON and a bunch of meaningless characters in the root node.

Host your site in NGINx

In the server node, specify a specific pathname and use lua script. 403 returns only a static page.

location ~ /api { You can customize the path here
    proxy_http_version 1.1;
    access_by_lua_file lua/access_limit.lua; Specifies the path to lua
    allow 127.0.0.1;
    proxy_pass http://127.0.0.1:8080;
    proxy_redirect default;
}

error_page 403 /403.html; # This is the response we return to the client when we deny access
location = /403.html { 
    root   html;
    allow all;
}
Copy the code

Lua handles requests

Q: Do you need to connect to Redis every time you request it? A:OpenResty provides us with connection pool. Resources can be reused without causing resource tension

Let’s first define the basic parameters: Block_client = 1 // Used to record the lockout duration limt_client = 5 // Number of accesses per second local limit_expiry = 1 // Record the accesses to limit_expiry within seconds local max_count = 5 //limit_expiry Access within seconds Maximum number of visits within seconds

Main methods:

  1. Get_client_id method: This method is used to identify the user. You can take IP, token, cookie and so on and make a signature as the user’s access token. I’m just taking the original IP
local function get_client_id(a)    
   local headers = ngx.req.get_headers()
   local clientId = headers["X-Real-IP"] or headers["x_forwarded_for"] or ngx.var["remote_addr"] or "0.0.0.0"
   return clientId
end
Copy the code
  1. Release the connection
Disable Redis from connection pool
local function close_redis(client)
   if not client then
       return
   end
   -- Put the Redis connection back into the connection pool
   local ok, err = client:set_keepalive(pool_max_idle_time, pool_size)
   if not ok then
       ngx.say("redis connct err:",err)
       return client:close(a)end
end
Copy the code

Complete code:

Gitee.com/cergou/juej…

Write in the last

The main idea is to set a key that expires within N seconds. When a client initiates a request, the user identity is identified by get_client_id. Incrementing this key by 1 on each request, if this value exceeds our maximum value. Reject this user’s request and log this user to block_client. Reject the user request next time. The block_client expires. Users can access the service normally

Mind mapping: