我需要以查询参数(例如user:pass
)的形式向nginx发送一些基本的身份验证凭据(例如http://example.com?BASIC_AUTH=dXNlcjpwYXNz
),并能够以更常见的{{1 }}标头形式指向代理后面的目标服务器。
我已经能够使用正则表达式检索编码的身份验证字符串的值。问题在于,该值通常可能包含一些需要在URL中进行百分比编码的字符。 Es。 Authorization: Basic dXNlcjpwYXNz
-> user:pass!
变成?BASIC_AUTH=dXNlcjpwYXNzIQ==
因此,当我将请求转发到目标服务器时,我最终指定了目标服务器将拒绝的?BASIC_AUTH=dXNlcjpwYXNzIQ%3D%3D
,给出了401 Unauthorized。
在设置Authorization标头之前,如何强制nginx解码auth字符串?预先感谢您的帮助。
注意:由于某些特定于应用程序的限制,我无法首先在Authorization标头中发送auth字符串。
答案 0 :(得分:1)
不幸的是,nginx没有提供丰富的字符串操作集。我认为没有办法通过某些字符串进行全局搜索和替换(如果我们可以将所有%2B
替换为+
,将%2F
替换为{{ 1}}和/
与%3D
)。但是,在某些情况下,nginx会对某些字符串执行urldecoding-当此字符串成为URI的一部分时,它将被转发到上游代理服务器。
因此,我们可以向URI添加=
请求参数的值,并向我们自己发出代理请求:
BASIC_AUTH
也许这不是一个非常优雅的解决方案,但是它已经过测试并且可以正常工作。
使用openresty函数,可以用ngx_http_lua_module或ngx.escape_uri轻松解决:
# Main server block
server {
listen 80 default_server;
...
location / {
if ($arg_basic_auth) {
# "basic_auth" request argument is present,
# append "/decode_basic_auth/<BASE64_token>" to the URI
# and go to the next location block
rewrite ^(.*)$ /decode_basic_auth/$arg_basic_auth$1 last;
}
# No "basic_auth" request argument present,
# can do a proxy call from here without setting authorization headers
...
}
location /decode_basic_auth/ {
# This will be an internal location only
internal;
# Remove "basic_auth" request argument from the list of arguments
if ($args ~* (.*)(^|&)basic_auth=[^&]*(\2|$)&?(.*)) {
set $args $1$3$4;
}
# Some hostname for processing proxy subrequests
proxy_set_header Host internal.basic.auth.localhost;
# Do a subrequest to ourselfs, preserving other request arguments
proxy_pass http://127.0.0.1$uri$is_args$args;
}
}
# Additional server block for proxy subrequests processing
server {
listen 80;
server_name internal.basic.auth.localhost;
# Got URI in form "/decode_basic_auth/<BASE64_token>/<Original_URI>"
location ~ ^/decode_basic_auth/([^/]+)(/.*)$ {
proxy_set_header Authorization "Basic $1";
# Setup other HTTP headers here
...
proxy_pass http://<upstream_server>$2$is_args$args;
}
# Do not serve other requests
location / {
return 444;
}
}