当前位置: 首页 > news >正文

从认证到透传:用 Nginx 为 EasySearch 构建一体化认证网关

在构建本地或云端搜索引擎系统时,EasySearch 凭借其轻量、高性能、易部署等优势,逐渐成为众多开发者和技术爱好者的首选。但在实际部署过程中,如何借助 Nginx 为 EasySearch 提供高效、稳定且安全的访问入口,尤其是在身份认证方面,仍然是一个关键技术环节。

本教程将围绕 Basic Auth 认证机制展开,系统讲解如何通过 Nginx 实现安全防护、认证信息透传等常见配置场景,帮助你在多种实际部署环境中快速搭建可靠的访问控制机制。

无论你是在搭建家庭 NAS 服务,还是在企业环境中集成搜索引擎系统,本教程都能为你提供一套可落地、可复用的 Nginx 安全认证解决方案。。

下面是我的 Nginx 配置文件示例。我们通过 Docker 启动 Nginx 容器,并将本地编写好的配置文件挂载到容器中,从而实现自定义的反向代理和认证逻辑:

docker run -d \--name my-nginx \-p 80:80 \-v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf \nginx

default.conf配置如下:

server {listen 80;server_name localhost;# 根路径可选配置,如果你要一个欢迎页location / {return 200 'Nginx is running.\n';add_header Content-Type text/plain;}# 反向代理 EasySearch location /es/ {proxy_pass https://backend:9200/;# 修正请求头proxy_http_version 1.1;# proxy_pass_request_headers on; ÷proxy_set_header Host $host;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_set_header Connection "";# 可选:允许跨域访问(用于前端 AJAX 调试)add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';add_header Access-Control-Allow-Headers 'Authorization,Content-Type';# proxy_set_header Authorization "Basic YWRtaW46MTIzNDU2";# 清理路径前缀 `/es/`rewrite ^/es/(.*)$ /$1 break;}# 可选:静态资源支持# location /static/ {#     root /usr/share/nginx/html;# }
}

🌐 配置整体结构

server {listen 80;server_name localhost;
  • 监听端口:监听本地 80 端口(HTTP 默认端口)
  • 服务名称:用于匹配请求的 Host,这里是 localhost

🎉 欢迎页(根路径 /

location / {return 200 'Nginx is running.\n';add_header Content-Type text/plain;
}
  • 请求 / 会返回纯文本响应 "Nginx is running.",可用于验证 Nginx 是否启动正常。
  • add_header Content-Type text/plain:指定响应内容为纯文本。

🔁 /es/ 代理 EasySearch 后端服务


🚚 请求头处理

    proxy_http_version 1.1;proxy_set_header Host $host;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_set_header Connection "";
  • proxy_http_version 1.1:确保代理使用 HTTP/1.1,支持长连接。
  • Host:保留原始请求的主机名。
  • X-Real-IP / X-Forwarded-For:传递客户端真实 IP。
  • X-Forwarded-Proto:传递原始协议(http / https)。
  • Connection "":用于避免默认的 keep-alive 设置引起错误(推荐保留)。

🔐 可选的认证头(注释中)

# proxy_set_header Authorization "Basic YWRtaW46MTIzNDU2";
  • 可选开启,用于将认证信息转发到后端。
  • 上面的字符串是 admin:123456 的 base64 编码。可以根据需要开启。

🌍 CORS 设置(跨域)

add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'Authorization,Content-Type';
  • 允许任意源访问(前端页面可以跨域请求 /es/)。
  • 支持的方法:GET、POST、OPTIONS。
  • 允许传递的请求头:Authorization 和 Content-Type。
  • ✅ 适用于 AJAX 调试、前后端分离等场景。

🔧 URL 重写

rewrite ^/es/(.*)$ /$1 break;
  • 移除 /es/ 前缀,转发给后端。例如:
    用户请求 /es/_cat/indices 实际转发到 /cat/indices
  • break 表示在当前 location 中中止后续重写检查。

📦 可选静态资源(被注释掉)

# location /static/ {
#     root /usr/share/nginx/html;
# }
  • 若开启,可以直接通过 /static/xxx.js 访问 Nginx 本地 /usr/share/nginx/html/static/xxx.js 文件。

🔁 如果你想保留 /es/ 前缀,则删除 rewrite 行。


在启动服务后,当我们通过浏览器访问 Nginx 时,页面会弹出身份验证窗口。需要注意的是,这里的认证提示实际上来自后端的 EasySearch 服务,而非 Nginx 本身,说明请求中的认证信息未在 Nginx 层被处理或透传,因此由 EasySearch 发起了再次认证的要求。

image-20250424165739653

在输入正确的用户名和密码后,我们可以看到 Nginx 成功代理请求,并返回了来自 EasySearch 的 API 响应,说明认证流程已顺利通过,后端服务正常可用。

image-20250424165019942

如果希望由 Nginx 代为完成 EasySearch 的身份验证,也就是实现自动登录的效果,可以在配置文件中添加如下指令,将认证信息通过 HTTP 头部传递给后端:

proxy_set_header Authorization "Basic YWRtaW46YWRtaW4=";

其中,YWRtaW46YWRtaW4xMjM= 是使用 Base64 编码后的 用户名:密码 字符串(例如 admin:admin)。Nginx 在转发请求时会自动携带该 Header,从而实现对 EasySearch 的自动认证。

需要注意的是,Nginx 的配置文件修改后不会自动生效。为了确保配置被正确加载,需在每次更改配置文件后重启对应的容器服务。这是容器化部署中常见的操作流程,确保新配置被正确应用。

image-20250424165420050

为了更直观地观察请求行为,我们使用了 Postman 进行测试。可以发现,即使在 Postman 中未显式添加任何认证信息,依然能够成功访问 EasySearch 集群。这说明前端未输入认证信息,但由于 Nginx 曾经缓存了认证状态,或配置了自动透传,导致后端依旧接收到了有效的认证头,从而允许了访问。

这种现象虽然在测试中提升了访问便利性,但在实际部署中可能带来安全风险,因此在生产环境中建议对认证流程进行严格控制,确保后端服务不会因为前端认证机制的疏漏而被绕过。

image-20250424165032915

在一些教程中,常会提到一个名为 .htpasswd 的文件,它用于在 Nginx 层实现基本认证。当启用该机制后,Nginx 会对所有访问进行用户身份验证。

此时,是否将认证信息透传给后端服务,则由 proxy_pass_request_headers 参数决定。该参数默认值为 on,也就是说,当认证通过后,客户端发送的 Authorization 头部信息会被 Nginx 一并转发给后端服务。

为了验证这一行为,我编写了一个简单的 Flask 程序作为后端,用于观察请求中的 Header 内容。在真正将请求代理至 EasySearch 之前,我先让 Nginx 将请求反向代理到这个 Flask 应用,从而可以直观地查看是否存在 Authorization 头被透传的情况。

from flask import Flask, request,abort
import base64
app = Flask(__name__)@app.route('/')
def hello_world():print("📥 Headers received from Nginx:")print("Host:", request.headers.get('Host'))print("X-Real-IP:", request.headers.get('X-Real-IP'))print("X-Forwarded-For:", request.headers.get('X-Forwarded-For'))print("X-Forwarded-Proto:", request.headers.get('X-Forwarded-Proto'))print(request.headers)auth_header = request.headers.get('Authorization')print("Authorization:", auth_header)if not auth_header or not auth_header.startswith('Basic '):abort(401, description="Missing or invalid Authorization header")# 解码 base64encoded = auth_header.split(' ')[1]decoded = base64.b64decode(encoded).decode('utf-8')  # e.g. admin:123456username, password = decoded.split(':', 1)print(username, password)return 'Hello World!'if __name__ == '__main__':app.run(host='0.0.0.0', port=8000,debug=True)

这个是flask的打印的结果.

Host: secure-nginx.orb.local
X-Real-IP: 192.168.215.1
X-Forwarded-For: 192.168.215.1
X-Forwarded-Proto: http
Host: secure-nginx.orb.local
X-Real-Ip: 192.168.215.1
X-Forwarded-For: 192.168.215.1
X-Forwarded-Proto: http
Authorization: Basic YWRtaW46YWRtaW4=
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh-TW;q=0.9,zh;q=0.8
Cookie: perf_dv6Tr4n=1Authorization: Basic YWRtaW46YWRtaW4=
admin admin
192.168.X.X - - [24/Apr/2025 15:55:59] "GET / HTTP/1.1" 200 -

为了解决双重认证的问题,我们启用了认证信息透传的配置(默认的roxy_pass_request_headers on;)。启用该配置后,用户只需在访问 Nginx 时进行一次手动身份验证。Nginx 会将用户提供的凭证通过 HTTP Header 透传至后端的 EasySearch 服务,从而避免二次认证。当用户直接访问 EasySearch 时,依然需要单独输入凭证进行认证;但通过 Nginx 访问时,只需在前端认证一次即可完成整个请求流程。

curl -k https://easysearch:9200        {"error":{"root_cause":[{"type":"security_exception","reason":"Missing authentication information for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"Security\" charset=\"UTF-8\""}}],"type":"security_exception","reason":"Missing authentication information for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"Security\" charset=\"UTF-8\""}},"status":401}⏎                                                                                          
-------curl -v -u "admin:admin" http://nginxhost/es/*   Trying 192.168.5.171:9201...
* Connected to 192.168.5.171 (192.168.5.171) port 9201
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Request CERT (13):
* (304) (IN), TLS handshake, Certificate (11):
* SSL certificate problem: self signed certificate
* Closing connection
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* Server auth using Basic with user 'admin'
> GET /es/ HTTP/1.1
> Host: localhost
> Authorization: Basic YWRtaW46YWRtaW4=
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.27.4
< Date: Thu, 24 Apr 2025 07:45:10 GMT
< Content-Type: application/json; charset=UTF-8
< Content-Length: 552
< Connection: keep-alive
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, OPTIONS
< Access-Control-Allow-Headers: Authorization,Content-Type
< 
{"name" : "easysearch-node1","cluster_name" : "infinilabs","cluster_uuid" : "VcMD__DwSYSUqear8wp-XA","version" : {"distribution" : "easysearch","number" : "1.11.1","distributor" : "INFINI Labs","build_hash" : "4d0be0343919fb1a605e3c8284326b7e069eb9bf","build_date" : "2025-03-14T09:33:12.182925Z","build_snapshot" : false,"lucene_version" : "8.11.4","minimum_wire_lucene_version" : "7.7.0","minimum_lucene_index_compatibility_version" : "7.7.0"},"tagline" : "You Know, For Easy Search!"
}
* Connection #0 to host localhost left intact

本次将 Nginx 的访问认证密码修改为 admin123 后,发现在请求过程中出现了两次身份验证的提示。具体表现为:当用户输入错误的密码时,Nginx 会首先返回一次 401 Unauthorized。由于 Nginx 与 EasySearch 使用了不同的认证信息,Nginx 在将请求头(包括 Authorization 字段)转发至 EasySearch 时,EasySearch 检测到凭据不匹配,也会返回一次 401。由此导致了双重身份认证失败的现象,影响了正常访问流程。

curl -v -u "admin:admin" http://localhost/es/*   Trying 192.168.5.171:9201...
* Connected to 192.168.5.171 (192.168.5.171) port 9201
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Request CERT (13):
* (304) (IN), TLS handshake, Certificate (11):
* SSL certificate problem: self signed certificate
* Closing connection
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* Server auth using Basic with user 'admin'
> GET /es/ HTTP/1.1
> Host: localhost
> Authorization: Basic YWRtaW46YWRtaW4=
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.27.4
< Date: Thu, 24 Apr 2025 09:21:09 GMT
< Content-Type: text/html
< Content-Length: 179
< Connection: keep-alive
* Authentication problem. Ignoring this.
< WWW-Authenticate: Basic realm="Restricted Area"
< 
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.27.4</center>
</body>
</html>
* Connection #0 to host localhost left intact
❰xu❙~/OrbStack/docker/containers/secure-nginx/etc/nginx❱✔≻ curl -v https://192.168.5.171:9201/         (base) 17:21:09curl -v -u "admin:admin123" http://localhost/es/*   Trying 192.168.5.171:9201...
* Connected to 192.168.5.171 (192.168.5.171) port 9201
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Request CERT (13):
* (304) (IN), TLS handshake, Certificate (11):
* SSL certificate problem: self signed certificate
* Closing connection
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.htmlcurl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
* Host localhost:80 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:80...
* Connected to localhost (::1) port 80
* Server auth using Basic with user 'admin'
> GET /es/ HTTP/1.1
> Host: localhost
> Authorization: Basic YWRtaW46YWRtaW4xMjM=
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.27.4
< Date: Thu, 24 Apr 2025 09:21:16 GMT
< Content-Type: application/json; charset=UTF-8
< Content-Length: 381
< Connection: keep-alive
* Authentication problem. Ignoring this.
< WWW-Authenticate: Basic realm="Security" charset="UTF-8"
< 
* Connection #0 to host localhost left intact
{"error":{"root_cause":[{"type":"security_exception","reason":"Missing authentication information for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"Security\" charset=\"UTF-8\""}}],"type":"security_exception","reason":"Missing authentication information for REST request [/]","header":{"WWW-Authenticate":"Basic realm=\"Security\" charset=\"UTF-8\""}},"status":401}
场景编号Nginx 是否开启认证EasySearch 是否开启认证实际认证次数说明
0 次完全开放,任何请求无需验证。
✅ 是1 次访问时直接弹出 EasySearch 的认证窗口,用户需输入凭证。
✅ 是1 次仅在 Nginx 层验证,验证通过后直接访问后端。
✅ 是✅ 是2 次(默认)Nginx 和 EasySearch 各自认证,用户需连续输入两次密码。
✅ 是✅ 是1 次(透传,proxy_pass_request_headers on;)Nginx 开启认证,并通过 proxy_set_header Authorization 透传给 EasySearch,用户仅需输入一次密码即可完成认证。

相关文章:

  • 解决 Windows10 下 UWP 应用无法使用本地代理
  • 运维面试题01
  • 【C/C++】深入理解指针(四)
  • MySQL的下载、安装、配置
  • 【OpenCV图像处理实战】从基础操作到工业级应用
  • Python实例题:使用Pvthon3编写系列实用脚本
  • 想要从视频中提取背景音乐怎么搞?其实视频提取音频非常简单
  • 如何在Spring Boot中禁用Actuator端点安全性
  • Java集合框架解析
  • matplotlib1-画成对数据图
  • 类的六个默认成员函数
  • ssrf与xxe
  • typescript学习笔记(全)
  • 避免事件“穿透”——Vue 中事件冒泡的理解与解决方案
  • HarmonyOS 框架基础知识
  • 力扣hot100 91-100记录
  • 如何构建高效的接口自动化测试框架?
  • Java转Go日记(十二):Channel
  • Java for循环中,如何在内循环跳出外循环?
  • MySQL 事务(详细版)
  • 我国风电光伏装机历史性超过火电
  • 四川公布一起影视盗版案例:1个网站2人团伙盗售30多万部
  • 马上评丨马拉松“方便门”被处罚,是一针清醒剂
  • 《2025职场人阅读报告》:超半数会因AI改变阅读方向
  • 中国天主教组织发唁电对教皇去世表示哀悼
  • 央行上海总部:上海个人住房贷款需求回升,增速连续半年回升