V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
colitude
V2EX  ›  NGINX

nginx 可以通过二级目录进行用户验证吗

  •  
  •   colitude · 83 天前 · 1363 次点击
    这是一个创建于 83 天前的主题,其中的信息可能已经有所发展或是发生改变。
    1. 用 xiuno 搭建了一个用来专门做笔记的论坛,主要看上它可以 web 端访问,手机也可以随时查阅,搜索可以标题搜索,也可以内容搜索。

    2. 放在腾讯云上面,在腾讯云的后台防火墙设置了 ip 白名单可以访问,但是现在想分享给认识的人也能访问也不想完全开放到互联网,但是又不想被一堆机器人扫描,因为目前我有个服务器为了做企业微信的验证,开放 80 端口,就一堆扫描爆破,只能通过记录日志,把那些 ip 拉入防火墙黑名单,黑名单容量有限还要定期删除一部分

    3. 另外我曾经建个自己用的 phpwind 论坛开放互联网访问,结果一堆机器人在上面发乱七八糟的广告信息

    4. 为了给某人访问,给他添加防火墙白名单也很麻烦,虽然可以通过腾讯云的 api 添加,但是一个人还好,人多了就要添加很多条 ip 白名单,而且手机的 ip 地址隔段时间还会变的

    5. 因为分享网站链接给别人是在微信上的,如果在 nginx 使用 auth_basic 认证,微信内置浏览器不会弹出输入用户名密码的框,直接显示 401 Authorization Required

    6. 目前我有一个想法,现在我有个企业微信,可以自建应用,可以拉朋友进应用里,他只有在应用里点击访问的菜单按钮,应用会接到后台服务器,后台软件会通过 2FA 验证器方式生成一个 6 位的数字(我把有效期设置为两个小时),然后就会生成一个包含验证数字的网址,比如 myxiuno.com/342567 ,后台软件也会用 2FA 验证器以同样的密钥在网站根目录生成一个作为验证的 342567 的文件夹,软件会每两小时重命名验证文件夹 然后 nginx 能否实现检测访问网址的二级目录和网站验证文件夹名字做比较,如果是一样的,那么就 proxy_pass http://127.0.0.1:8888/;#搭建的论坛访问端口 比如访问的网址是 myxiuno.com/342567/?thread-311.htm ,如果网站根目录的验证文件夹名字是 342567 ,那就可以正确访问到 http://127.0.0.1:8888/?thread-311.htm 。 但是如果是 myxiuno.com/?thread-311.htm ,或者验证码过期了 myxiuno.com/652092/?thread-311.htm ,那么就返回 404

    我目前是这样写配置的

            location / {  
                root C:\website;
                if (-f $request_filename)
                    {
                   proxy_pass http://127.0.0.1:8888/;
                    }
               
                  return 404;
            }
    

    可是提示错误

    nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in C:\phpstudy_pro\Extensions\Nginx1.15.11/conf/nginx.conf:275
    
    1. 请问我上面设想的功能能否通过 nginx 实现,如果能实现是我上面配置写的有问题吗,应该怎么修改
    6 条回复    2024-02-04 09:16:25 +08:00
    cdlnls
        1
    cdlnls  
       83 天前 via Android
    用 lua 脚本去实现比较方便。我有个网站就这么做的,访问一个特定的 url 后,lua 脚本里面获取客户端的 ip ,把 ip 加入到白名单,白名单有效时间几个小时。

    xx@opsc:/data/www/lua$ cat save_ip.lua
    -- save_ip.lua
    -- 获 取 客 户 端 IP 地 址
    local client_ip = ngx.var.remote_addr
    -- 设 置 shared dictionary 的 名 称 和 键
    local dict_name = "ip_dict"
    local dict_key = client_ip
    -- 设 置 过 期 时 间 为 3600 秒 ( 1 小 时 )
    local expire_time = 28800
    -- 将 IP 保 存 到 shared dictionary 并 设 置 过 期 时 间
    local ok, err = ngx.shared[dict_name]:set(dict_key, true, expire_time)
    if not ok then
    ngx.log(ngx.ERR, "Failed to save IP in dictionary: ", err)
    ngx.exit(500)
    end
    ngx.header.content_type = "text/plain"
    ngx.say('Added: ', client_ip)
    ngx.log(ngx.INFO, "IP saved: ", client_ip)
    xx@opsc:/data/www/lua$ cat check_ip.lua
    -- check_ip.lua
    --
    -- nginx.conf: lua_shared_dict ip_dict 10m;
    -- 获 取 客 户 端 IP 地 址
    local client_ip = ngx.var.remote_addr
    -- 设 置 shared dictionary 的 名 称 和 键
    local dict_name = "ip_dict"
    local dict_key = client_ip
    -- 设 置 白 名 单 , 这 里 假 设 白 名 单 为 一 个 Lua table
    local whitelist = {
    ["127.0.0.1"] = true,
    ["10.10.0.1"] = true,
    -- 添 加 其 他 白 名 单 IP
    }
    -- 检 查 是 否 在 白 名 单 中
    if whitelist[client_ip] then
    ngx.log(ngx.INFO, "IP is in whitelist: ", client_ip)
    else
    -- 检 查 shared dictionary 中 是 否 存 在 客 户 端 IP
    local ip_found = ngx.shared[dict_name]:get(dict_key)
    -- 如 果 IP 不 存 在 , 则 返 回 403
    if not ip_found then
    ngx.log(ngx.INFO, "IP not found: ", client_ip)
    ngx.exit(403)
    end
    ngx.log(ngx.INFO, "IP found: ", client_ip)
    end
    Vegetable
        2
    Vegetable  
       83 天前
    我看你描述了一大堆需求,路子不太对,不过既然已经到了这一步,还是看最后的问题吧

    proxy_pass 不能出现在 if 里边,但是你可以通过变量来变相实现这个配置。总结你的需求:如果匹配了,就 proxy_pass ,不匹配就 404 。

    一个可行的方案是:
    set $final_upstream = 必然 404 的地址;
    if (condition) {
    $final_upstream = http://127.0.0.1:8888/;
    }
    proxy_pass $final_upstream;

    这样也会有一些别的限制,nginx 要在启动时解析出所有可能的 upstream ,所以你的 127.0.0.1 或者 404 地址包含域名,就需要动态 dns 。
    colitude
        3
    colitude  
    OP
       83 天前
    @Vegetable if (condition) 这个 condition 要怎么写
    colitude
        4
    colitude  
    OP
       83 天前
    @cdlnls 谢谢,之前搜索答案的时候也出现过类似 lua 的解决方案,不过我现在用的 phpstudy 里面的 nginx ,找不到怎么开启 lua 模块,以为可以直接通过改 nginx.conf 实现,所以上来问问
    另外我的需求确实类似“访问一个特定的 url 后,lua 脚本里面获取客户端的 ip ,把 ip 加入到白名单,白名单有效时间几个小时”
    colitude
        5
    colitude  
    OP
       83 天前
    @Vegetable 或者说 nginx 能不能读取访问网址 myxiuno.com/342567/?thread-311.htm 中间那个 342567 作为一个变量,然后读取文件名,或者文件名里面的 342567 (这个两小时会更新的)作为另外一个变量做比对
    JaguarJack
        6
    JaguarJack  
       83 天前
    auth_request 呢?我没试过 Get 转发,你可以让你认证系统内的用户生成一个 token ,然后通过 auth_request 传递 token 到这个页面的认证下?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2785 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:35 · PVG 13:35 · LAX 22:35 · JFK 01:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.