Maison >base de données >Redis >Comment utiliser Lua pour le contrôle d'accès Nginx Redis
1. Nginx dispose de nombreuses façons de gérer le contrôle d'accès, et il existe de nombreux effets de mise en œuvre, tels que la plage IP d'accès, les restrictions de contenu d'accès, les restrictions de fréquence d'accès, etc.
2. L'utilisation de Nginx+Lua+Redis pour la restriction d'accès prend principalement en compte la nécessité d'un contrôle d'accès rapide dans les environnements à forte concurrence.
3. Le processus de traitement des requêtes Nginx est divisé en 11 étapes, qui sont :
post-read、server-rewrite、find-config、rewrite、post-rewrite、 preaccess、access、post-access、try-files、content、log.
Dans openresty, vous pouvez trouver :
set_by_lua,access_by_lua,content_by_lua,rewrite_by_lua等方法。
Ensuite, le contrôle d'accès devrait être l'étape d'accès.
Selon la pensée logique normale, la solution de contrôle d'accès à laquelle nous penserions est la suivante :
1. Détecter si c'est interdit ? =》Oui, si l'interdiction a expiré : Oui, effacer l'enregistrement, renvoyer 200, accès normal ; Non, renvoyer 403 =》Non, renvoyer 200, accès normal
2. 1 traitement
3. Vérifiez si la fréquence d'accès dépasse la limite. Si elle dépasse la limite, un enregistrement interdit sera ajouté et 403 sera renvoyé
C'est une solution simple. le temps d'interdiction d'accès est importé via l'algorithme et la courbe concave augmente à chaque fois.
Ajoutez d'abord le fichier de configuration vhost pour nginx. La partie vhost.conf est la suivante :
lua_package_path "/usr/local/openresty/lualib/?.lua;;";#告诉openresty库地址lua_package_cpath "/usr/local/openresty/lualib/?.so;;"; error_log /usr/local/openresty/nginx/logs/openresty.debug.log debug; server { listen 8080 default; server_name www.ttlsa.com; root /www/openresty; location /login { default_type 'text/html'; access_by_lua_file "/usr/local/openresty/nginx/lua/access_by_redis.lua";#通过lua来处理访问控制 } }
Access_by_redis.lua
Après avoir fait référence à l'implémentation de v2ex.com, nous avons constaté qu'en utilisant un simple La solution de stockage de chaînes est suffisante. C'était suffisant, c'est pourquoi Redis a été choisi comme méthode de stockage. Les clés sont :
Enregistrement de connexion utilisateur : utilisateur :127.0.0.1 :heure (horodatage unix)
Restrictions d'accès : bloc :127.0.0.1
Connectez-vous d'abord à Redis :
local red = redis:new()function M:redis() red:set_timeout(1000)local ok, err = red:connect("127.0.0.1", 6379)if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end end
Selon notre plan logique, deuxièmement Le premier L'étape consiste à vérifier si c'est interdit. Ensuite, nous vérifierons le bloc : 127.0.0.1. Si les données sont recherchées, vérifiez si le délai n'a pas expiré, 403 sera renvoyé directement. :
function M:check1()local time=os.time() --system timelocal res, err = red:get("block:"..ngx.var.remote_addr)if not res then -- redis error ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error endif type(res) == "string" then --if red not null then type(red)==string if tonumber(res) >= tonumber(time) then --check if forbidden expired ngx.exit(ngx.HTTP_FORBIDDEN) --ngx.say("forbidden") end end }
Ensuite, nous vérifierons si la fréquence d'accès a été dépassée. Si elle est trop élevée, elle sera mise sur liste noire. La façon d'y parvenir est de détecter si la valeur de user:127.0.0.1:time dépasse. le standard :
function M:check2()local time=os.time() --system timelocal res, err = red:get("user:"..ngx.var.remote_addr..":"..time)if not res then -- redis error ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error endif type(res) == "string" then if tonumber(res) >= 10 then -- attack, 10 times request/s red:del("block:"..self.ip) red:set("block:"..self.ip, tonumber(time)+5*60 ) --set block time ngx.exit(ngx.HTTP_FORBIDDEN) end end end
Enfin, pensez à prévoir un temps pour chaque visite Auto-augmentation, user:127.0.0.1:time:
function M:add()local time=os.time() --system time ok, err = red:incr("user:"..ngx.var.remote_addr..":"..time)if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) --redis get data error end end
Ensuite, testez, forcez le rafraîchissement du navigateur plusieurs fois, et constatez qu'au bout d'un moment, 403 est renvoyé, ok, c'est fait.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!