halo-dev / halo

强大易用的开源建站工具。
https://www.halo.run
GNU General Public License v3.0
34.03k stars 9.71k forks source link

使用nginx auth_basic_user_file 模块bug #6685

Closed printinfo closed 1 month ago

printinfo commented 1 month ago

系统信息

外部链接:暂不公开(如协作需要请联系) 启动时间:2024/9/20 12点33分 版本:2.19.0 数据库:mysql 8.0/H2 操作系统:Ubuntu 20.04.6 LTS / CentOS Linux release 7.6.1810 (Core) nginx:nginx/1.18.0 (Ubuntu) / nginx/1.20.1 Centos apache2-utils :2.4.41-4ubuntu3.21 / httpd-tools-2.4.6-99.el7.centos.1.x86_64

使用的哪种方式运行?

Docker

发生了什么?

多平台测试结果相同 Ubuntu20.04 / Cenots 7 多部署方式测试结果相同 Docker / JAR 使用nginx 反向代理 到halo程序 并auth_basic_user_file 模块 设置登录账号密码 出现重复登录情况,一直鉴权失败。nginx配置如下

server {
    listen 443 ssl;
    server_name xxx;
    ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    client_max_body_size 50M;

    location / {
        auth_basic "require auth";
        auth_basic_user_file /etc/nginx/htpasswd;
        proxy_set_header Host $host;
        proxy_set_header Authorization $http_authorization;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;
    }

    access_log /data/logs/nginx/xxx/access_log;
    error_log /data/logs/nginx/xxx/error_log;
}

htpasswd -c /etc/nginx/htpasswd user1

多次确认登录的密码没有错误,并且在nginx上把反向代理切换到其他静态页面会登录成功。

复现步骤

  1. 根据官方文档部署halo程序
  2. 下载安装nginx
  3. 下载安装httpd-tools
  4. 使用htpasswd创建账户
  5. 配置反向代理到halo项目
  6. 通过浏览器访问项目

相关日志输出

No response

附加信息

No response

ruibaby commented 1 month ago

相同问题:https://github.com/halo-dev/halo/issues/5408

/triage duplicate

JohnNiang commented 1 month ago

建议先移除掉下面这一行试试:

        proxy_set_header Authorization $http_authorization;
printinfo commented 1 month ago

建议先移除掉下面这一行试试:

        proxy_set_header Authorization $http_authorization;

删除这个试过 也不行

JohnNiang commented 1 month ago

尝试添配置下内容:

server {
    server_name halo;
    location / {
        set $auth_basic_enabled "Require Auth";
        if ($http_authorization ~* "Bearer") {
            # Disable Basic Auth for Halo PAT
            set $auth_basic_enabled "off";
        }
        auth_basic $auth_basic_enabled;
        auth_basic_user_file /etc/nginx/conf.d/htpasswd;
        proxy_set_header Host $host;
        if ($http_authorization ~* "Basic") {
            # Don't pass Basic Authentication here.
            set $http_authorization "";
        }
        proxy_set_header Authorization $http_authorization;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://host.docker.internal:8090/;
    }
}

我实际测试是可以正常访问的,并且不影响 Halo 的个人令牌。测试结果如下所示:

http http://localhost:8080 Authorization:"Bearer pat_xxx"
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Mon, 23 Sep 2024 15:23:29 GMT
Expires: 0
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Server: nginx/1.27.1
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Invalid JWT serialization: Missing dot delimiter(s)", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
http http://localhost:8080
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Content-Length: 179
Content-Type: text/html
Date: Mon, 23 Sep 2024 15:21:45 GMT
Server: nginx/1.27.1
WWW-Authenticate: Basic realm="Require Auth"

<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
http -a admin:openadmin http://localhost:8080 -pHh
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46b3BlbmFkbWlu
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.3

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Language: en-CN
Content-Type: text/html
Date: Mon, 23 Sep 2024 15:26:19 GMT
Expires: 0
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Server: nginx/1.27.1
Transfer-Encoding: chunked
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
content-encoding: gzip
set-cookie: XSRF-TOKEN=43950cf6-4cdc-43a0-8dbb-9b87a73feac9; Path=/
printinfo commented 1 month ago

尝试添配置下内容:

server {
  server_name halo;
    location / {
        set $auth_basic_enabled "Require Auth";
        if ($http_authorization ~* "Bearer") {
            # Disable Basic Auth for Halo PAT
            set $auth_basic_enabled "off";
        }
        auth_basic $auth_basic_enabled;
        auth_basic_user_file /etc/nginx/conf.d/htpasswd;
        proxy_set_header Host $host;
        if ($http_authorization ~* "Basic") {
            # Don't pass Basic Authentication here.
            set $http_authorization "";
        }
        proxy_set_header Authorization $http_authorization;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://host.docker.internal:8090/;
    }
}

我实际测试是可以正常访问的,并且不影响 Halo 的个人令牌。测试结果如下所示:

http http://localhost:8080 Authorization:"Bearer pat_xxx"
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Mon, 23 Sep 2024 15:23:29 GMT
Expires: 0
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Server: nginx/1.27.1
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
WWW-Authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Invalid JWT serialization: Missing dot delimiter(s)", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
http http://localhost:8080
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Content-Length: 179
Content-Type: text/html
Date: Mon, 23 Sep 2024 15:21:45 GMT
Server: nginx/1.27.1
WWW-Authenticate: Basic realm="Require Auth"

<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>
http -a admin:openadmin http://localhost:8080 -pHh
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46b3BlbmFkbWlu
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.3

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Language: en-CN
Content-Type: text/html
Date: Mon, 23 Sep 2024 15:26:19 GMT
Expires: 0
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
Server: nginx/1.27.1
Transfer-Encoding: chunked
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 0
content-encoding: gzip
set-cookie: XSRF-TOKEN=43950cf6-4cdc-43a0-8dbb-9b87a73feac9; Path=/

配置修改之后 问题已经解决

JohnNiang commented 1 month ago

Halo 2.20(即将发布)我们将默认禁用 Basic 认证。届时可移除多余的配置。

https://github.com/halo-dev/halo/pull/6689