【问题标题】:Conditional auth_basic_user_file depending on the request path有条件的 auth_basic_user_file 取决于请求路径
【发布时间】:2022-01-18 09:58:35
【问题描述】:

我想根据请求的路径授权用户。例如,只有user1user2 应该有权访问/projects/1

我的/etc/nginx/.htpasswd 看起来像这样:

user1:$hashed_psswd1
user2:$hashed_psswd2
user3:$hashed_psswd3
...

这是 nginx 配置中的 location 块:

location ~ /projects(/.*) {
    auth_basic "Please provide credentials";
    auth_basic_user_file /etc/nginx/.htpasswd;
    include /var/www/html/myapp.com/config/nginx/git-http-backend.conf;
} 

还有 rails 动作:

def git
  redirect_to "#{Rails.configuration.x.domain}/projects/#{@project.id}"
end

身份验证似乎有效:

$ git clone http://localhost:3000/projects/1
Cloning into '1'...
Username for 'http://localhost:3001': user1  
Password for 'http://deploy@localhost:3001': 
remote: Enumerating objects: 94, done.
# ... it successfully clones the git repo...

问题是user3 可以克隆项目1,但他应该不能克隆这样的项目。

那么如何根据请求的路径在 nginx + rails 中授权用户呢?

【问题讨论】:

  • 你想在哪里授权用户?如果您想在后端执行此操作,请检查并处理 Authorization 标头。如果你想用 nginx 来做,使用几个密码文件。使用正则表达式位置有什么问题?为什么不用前缀location /projects/ { ... }
  • 嗨@Ivan。我尝试使用带有location ~ /projects(/.*) { set $file /projects$1/.htpasswd; auth_basic_user_file $file; } 的项目特定密码文件,但发现auth_basic_user_file doesn't allow a variable as argument。目标是使用登录名+密码进行授权。如果不能用 nginx 完成,我可以编写一个 bash 或 ruby​​ CGI 脚本并让 rails 指向它来授权用户。
  • 但是auth_basic_user_file 指令上的 nginx 文档明确指出文件名可以包含变量(否则我不建议这样做)。您所指的答案是8岁。你用的是什么 nginx 版本?
  • 我使用的是 nginx 1.20.1。

标签: ruby-on-rails git nginx


【解决方案1】:

这是我刚刚使用 OpenResty 1.17.8.2(基于 nginx 1.17.8 核心)测试的配置,可以确认它是可行的:

map $uri $realm {
    ~^/projects/    "Protected projects";
    ~^/images/      "Protected images";
    default         off;
}
map $uri $authfile {
    ~^/projects/    /path/to/.htpasswd_projects;
    ~^/images/      /path/to/.htpasswd_images;
}
server {
    ...
    auth_basic $realm;
    auth_basic_user_file $authfile;
    ...
}

.htpasswd_projects.htpasswd_images 文件包含每个自己的用户/密码列表。通过上面的配置,每个以/projects/ 开头的URI 都受到基本授权的保护,并且只对htpasswd_projects 文件中列出的用户可用,每个以/images/ 开头的URI 都受到基本授权的保护,并且只对列出的用户可用htpasswd_images 文件,其余 URI 无需任何人授权即可使用。

更新

这是另一个示例,根据请求的 URI 使用动态生成的 .htpasswd 路径:

location ~ ^/projects/(?<project_id>[^/]+) {
    if (!-f /var/www/projects/$project_id/.htpasswd) {
        # '.htpasswd' file for the requested project does not exists
        # assuming wrong project ID is given, returning HTTP 404 Not found
        return 404;
    }
    auth_basic "Please provide credentials for project $1";
    auth_basic_user_file /var/www/projects/$project_id/.htpasswd;
    ...
}

这适用于以下.htpasswd 文件树:

/var/www/projects
         ├── 1
         │   └── .htpasswd
         ├── 2
         │   └── .htpasswd
         ...

您可以将此projects 目录放置在您想要的任何位置,它不依赖于 Web 服务器根目录。

【讨论】:

    猜你喜欢
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2016-03-02
    • 1970-01-01
    • 2017-12-08
    相关资源
    最近更新 更多