Nginx-解码URL查询参数并将其作为请求头转发
我需要发送一些基本的身份验证凭据。用户:以查询参数es的形式传递给nginx。http://example.com?BASIC_AUTH=dXNlcjpwYXNz 并且能够以更常见的授权方式(基本的dXNlcjpwYXNz头格式)将它们转发到代理后面的目标服务器 我已经能够用正则表达式检索编码的auth字符串的值。问题是,该值通常可能包含一些需要在URL中进行百分比编码的字符。锿。用户:通过!->?BASIC_AUTH=dXNlcjpwYXNzIQ==变成?BASIC_AUTH=dXNlcjpwYXNzIQ%3D%3D 因此,当我将请求转发到目标服务器时,我最终指定了授权:Basic dXNlcjpwYXNzIQ%3D%3D,目标服务器将拒绝该授权,并给出401个未经授权的消息 在设置授权头之前,如何强制nginx解码auth字符串?提前感谢你的帮助 注意:由于某些特定于应用程序的限制,我无法首先在授权标头中发送auth字符串。Pure nginx解决方案 不幸的是,nginx不提供富字符串操作集。我认为没有一种方法可以通过某个字符串进行全局搜索和替换,如果我们可以将所有%2B替换为+,%2F替换为/和%3D替换为=,则该字符串可能是一种解决方案。然而,在某些情况下,nginx会对某个字符串执行url解码——当该字符串成为将转发到上游代理服务器的URI的一部分时 因此,我们可以向URI添加一个基本的_AUTH request参数值,并向自己发出代理请求:Nginx-解码URL查询参数并将其作为请求头转发,nginx,basic-authentication,urlencode,url-encoding,Nginx,Basic Authentication,Urlencode,Url Encoding,我需要发送一些基本的身份验证凭据。用户:以查询参数es的形式传递给nginx。http://example.com?BASIC_AUTH=dXNlcjpwYXNz 并且能够以更常见的授权方式(基本的dXNlcjpwYXNz头格式)将它们转发到代理后面的目标服务器 我已经能够用正则表达式检索编码的auth字符串的值。问题是,该值通常可能包含一些需要在URL中进行百分比编码的字符。锿。用户:通过!->?BASIC_AUTH=dXNlcjpwYXNzIQ==变成?BASIC_AUTH=dXNlcjpw
# 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;
}
}
也许这不是一个非常优雅的解决方案,但它已经过测试并且可以工作
OpenResty/ngx_http_lua_模块
这可以通过以下功能轻松解决:
server {
listen 80 default_server;
...
location / {
set $auth $arg_basic_auth;
if ($args ~* (.*)(^|&)basic_auth=[^&]*(\2|$)&?(.*)) {
set $args $1$3$4;
}
rewrite_by_lua_block {
ngx.var.auth = ngx.unescape_uri(ngx.var.auth)
}
proxy_set_header Authorization "Basic $auth";
# Setup other HTTP headers here
...
proxy_pass http://<upstream_server>;
}
}
纯nginx溶液
不幸的是,nginx不提供富字符串操作集。我认为没有一种方法可以通过某个字符串进行全局搜索和替换,如果我们可以将所有%2B替换为+,%2F替换为/和%3D替换为=,则该字符串可能是一种解决方案。然而,在某些情况下,nginx会对某个字符串执行url解码——当该字符串成为将转发到上游代理服务器的URI的一部分时
因此,我们可以向URI添加一个基本的_AUTH request参数值,并向自己发出代理请求:
# 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;
}
}
也许这不是一个非常优雅的解决方案,但它已经过测试并且可以工作
OpenResty/ngx_http_lua_模块
这可以通过以下功能轻松解决:
server {
listen 80 default_server;
...
location / {
set $auth $arg_basic_auth;
if ($args ~* (.*)(^|&)basic_auth=[^&]*(\2|$)&?(.*)) {
set $args $1$3$4;
}
rewrite_by_lua_block {
ngx.var.auth = ngx.unescape_uri(ngx.var.auth)
}
proxy_set_header Authorization "Basic $auth";
# Setup other HTTP headers here
...
proxy_pass http://<upstream_server>;
}
}