Nginx重写请求后将url?后的参数去除

本文介绍如何使用 Nginx 进行 URL 重写,并解释如何在重定向过程中保留特定参数的方法。例如,将 http://example.com/test.php?para=xxx&p=xx 重写为 http://example.com/new.php?p=xx 的具体配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用?结尾
    注意,关键点就在于“?”这个尾缀。重定向的目标地址结尾处如果加了?号,则不会再转发传递过来原地址的问号?后面的参数那部分。
    假如又想保留某个特定的参数,那又该如何呢?可以利用Nginx本身就带有的$arg_PARAMETER参数自行补充来实现。
例如:
把http://example.com/test.php?para=xxx&p=xx 重写向到 http://example.com/new.php?p=xx
可以写成:rewrite  ^/test.php  /new.php?p=$arg_p?  permanent;

转载于:https://my.oschina.net/ffse54s/blog/1499295

<think>我们有一个需求:将URL中的token参数移动到请求头中。例如,当请求URL为`http://example.com?token=abc123`时,我们希望Nginx能够提取这个token参数,并将其添加到请求头中(例如`Authorization:Bearerabc123`),然后传递给后端服务器。解决方案:我们可以使用Nginx的`rewrite`指令来修改请求,但更合适的方式是使用`set`指令结合变量操作来捕获参数,然后通过`proxy_set_header`将捕获的参数值设置为新的请求头。步骤:1.使用`$arg_token`变量获取URL中的token参数值。2.使用`proxy_set_header`指令将获取到的值设置到请求头(例如`Authorization`)中。注意:由于URL参数可能出现在任何位置,我们不需要修改URL(即不需要重写URL),只需修改请求头。配置示例:```nginxserver{listen80;server_nameexample.com;location/{#如果URL中存在token参数,则将其值赋给变量$token_valueset$token_value$arg_token;#如果$token_value不为空,则将其添加到Authorization头if($token_value){#注意:这里我们使用Bearer方案,你也可以根据需求调整proxy_set_headerAuthorization"Bearer$token_value";}#代理到后端proxy_passhttp://backend_server;}}```但是,请注意,使用`if`指令在Nginx配置中需要谨慎,因为它在某些上下文中可能会有副作用。上述配置在`location`块内使用`if`来检查变量是否非空,然后设置请求头,这是可行的。另一种更安全且避免`if`的方式是直接设置请求头,如果`$arg_token`为空,则设置一个空值。但这样可能会传递一个空的Authorization头,可能不是我们想要的。我们可以使用`map`指令来条件性地构造变量。使用`map`的配置:```nginx#在http块中定义maphttp{map$arg_token$auth_header{default"";#默认值为空~^(?<token>.+)$"Bearer$token";#如果token参数存在且非空,则构造Bearertoken字符串}server{listen80;server_nameexample.com;location/{#将map得到的$auth_header变量设置为Authorization头proxy_set_headerAuthorization$auth_header;proxy_passhttp://backend_server;}}}```这种方法更安全,因为`map`指令是在请求处理的早期阶段执行的,并且避免了`if`指令。注意:如果URL中没有token参数,则`$auth_header`为空,此时不会设置Authorization头(或者设置为空,取决于后端是否允许空头)。如果后端需要Authorization头必须存在,那么这种方式可能不够,因为当没有token时,请求头中就没有Authorization。因此,我们可能需要确保只有在token存在时才设置头,否则不设置。我们可以使用`if`块来条件性地设置,或者使用两个`proxy_set_header`指令,其中一个用于清除头,另一个用于设置。但是,更简洁的方式是使用`map`来生成一个变量,然后根据这个变量是否为空来决定是否设置头。然而,Nginx的`proxy_set_header`在值为空时默认不会传递该头。所以,使用`map`的方式,当没有token时,`$auth_header`为空,那么`proxy_set_headerAuthorization$auth_header;`实际上不会设置Authorization头(即不会传递该头到后端)。这符合我们的需求。因此,推荐使用`map`的方式。但是,如果我们需要支持多种认证方式(比如同时支持token参数和已有的Authorization头)?这个需求只是要求将URL中的token移动到请求头,如果请求头已经存在Authorization,那么可能会被覆盖。如果需求是当请求头不存在Authorization时,才使用URL中的token,那么我们需要更复杂的逻辑。根据需求,我们只要求将URL中的token移动到请求头,因此直接覆盖也是合理的。如果需求是补充而不是覆盖,则需要先检查请求头是否存在。综上所述,我们使用`map`方法来实现。另外,我们还需要注意,如果URL中的token参数被移动到请求头,那么我们应该在转发请求之前从URL中移除它,以避免后端服务器再次处理它。但需求并没有要求移除,所以我们可以选择移除或不移除。如果后端服务器不需要这个参数,最好移除,以避免潜在的安全风险(如日志记录)或干扰。移除token参数:我们可以使用`rewrite`指令来重写URL,去掉token参数。但是,`rewrite`会改变URL,可能会影响请求。另一种方法是在`proxy_pass`中使用变量来构造不含token参数URL。在Nginx中,我们可以通过设置`$args`变量来修改查询字符串。在设置`$args`时,我们可以移除token参数。例如:```nginxset$args$query_string_without_token;```我们可以使用正则表达式来移除token参数。但是,查询字符串可能包含多个参数,移除token参数需要小心处理。我们可以使用`map`来构建新的查询字符串,或者使用`if`和正则表达式匹配。在Nginx中,我们可以使用以下方式移除token参数:```nginx#使用set指令和正则表达式移除token参数set$original_args$args;set$args"";if($original_args~(.*)(?:&?token=[^&]*)){set$args$1;}```但是,这种方法比较复杂,而且使用多个`if`和`set`可能会导致问题。更简单的方法是使用`$query_string`变量,然后使用正则表达式捕获。但是,Nginx没有内置移除特定参数的功能,我们可以使用第三方模块,如ngx_lua,但这里我们尽量使用标准模块。我们可以这样:```nginx#在server块或location块中if($args~(.*)(?:^|&)token=[^&]*(.*)){set$args$1$2;}```但是,这个正则表达式可能不完美,特别是当token是第一个参数时,移除后可能会留下一个多余的`&`或`?`。更好的做法是使用`map`来构造新的查询字符串,但比较复杂。考虑到需求,如果不需要移除,我们可以不处理。但如果需要移除,我们可以采用以下方法:```nginxset$new_args$args;if($new_args~*"(.*)&token=[^&]*(.*)"){set$new_args$1$2;}if($new_args~*"^token=[^&]*(.*)"){set$new_args$1;}#然后使用$new_args作为新的查询字符串set$args$new_args;```但这种方法有多个`if`,且可能无法处理所有情况(比如token在中间,或者有多个token参数,但通常只有一个)。由于这个需求不是必须的,我们暂时不考虑移除。如果确实需要移除,可以在配置中添加上述逻辑。现在,我们给出完整的配置(包括移除token参数):注意:移除参数可能会影响性能,且实现稍复杂,因此根据实际情况决定是否使用。完整配置(包括移动token到请求头和移除URL中的token参数):```nginxhttp{#定义map,用于生成Authorization头map$arg_token$auth_header{default"";~^(?<token>.+)$"Bearer$token";}server{listen80;server_nameexample.com;location/{#设置Authorization头proxy_set_headerAuthorization$auth_header;#移除URL中的token参数set$original_args$args;set$args"";#如果原始参数匹配,则移除token参数if($original_args~(.*)(?:&?token=[^&]*)){set$args$1;}proxy_passhttp://backend_server;}}}```但是,上述移除参数的正则表达式可能不够完善,例如:-当token是唯一的参数时,移除后应为空。-当token是第一个参数时,移除后剩下的参数应该以`?`开头,但我们的正则表达式会保留`&`,所以需要调整。改进的移除方法:```nginxset$new_args$args;#如果token参数存在,则移除if($new_args~*"^token=[^&]*(?:&(.*))?$"){set$new_args$1;}if($new_args~*"^(.*)&token=[^&]*(.*)$"){set$new_args$1$2;}set$args$new_args;```但是,这种方法仍然有多个`if`,且可能无法覆盖所有情况。考虑到复杂性和性能,如果不需要移除,建议不做处理。或者,我们可以使用Nginx的ngx_http_rewrite_module的`rewrite`指令来重写URL,但`rewrite`会改变URL路径,不适合只修改查询参数。因此,我们推荐只移动token到请求头,不移除URL中的token参数。如果必须移除,可以考虑使用更高级的模块(如lua)或者在后端处理。最终配置(只移动,不移除):```nginxhttp{map$arg_token$auth_header{default"";~^(?<token>.+)$"Bearer$token";}server{listen80;server_nameexample.com;location/{proxy_set_headerAuthorization$auth_header;proxy_passhttp://backend_server;}}}```这样,当请求URL中有token参数时,会将其值放入Authorization头(Bearer方案)并传递给后端,而URL中的token参数仍然存在。相关问题:1.如何防止Nginx将空Authorization头传递给后端?答:使用map时,当没有token参数,$auth_header为空,则proxy_set_headerAuthorization$auth_header;不会设置任何值,即不会传递Authorization头。2.如果URL中有多个token参数会怎样?答:Nginx的$arg_token变量只取第一个token参数的值。如果URL中有多个token参数,则$arg_token是第一个出现的token参数的值。因此,我们只取第一个。3.如何同时支持URL中的token和已有的Authorization头?答:如果请求头已经存在Authorization,而URL中也有token,那么上述配置会覆盖已有的Authorization头。如果需要保留原有的Authorization头,则不能覆盖。我们可以这样:只有当请求头中不存在Authorization时,才使用URL中的token。这需要更复杂的配置,例如使用$http_Authorization变量(代表请求中的Authorization头)来判断。我们可以在map中增加条件,或者使用if块。例如:```nginxhttp{map$arg_token$auth_header_from_url{default"";~^(?<token>.+)$"Bearer$token";}server{listen80;server_nameexample.com;location/{#如果请求头中没有Authorization,并且URL中有token,则使用URL中的token设置Authorization头if($http_Authorization=""){proxy_set_headerAuthorization$auth_header_from_url;}proxy_passhttp://backend_server;}}}```注意:使用`if`指令要小心,最好在`location`块中避免使用`if`,除非必要。另一种方法是使用两个`map`和变量组合。更安全的方式:```nginxhttp{map$arg_token$auth_header_from_url{default"";~^(?<token>.+)$"Bearer$token";}#判断请求头Authorization是否存在map$http_Authorization$final_auth_header{#如果请求头Authorization不为空,则使用原有的(即不改变)~.+$http_Authorization;#否则,使用来自URL的token构造的头default$auth_header_from_url;}server{listen80;server_nameexample.com;location/{proxy_set_headerAuthorization$final_auth_header;proxy_passhttp://backend_server;}}}```这样,如果请求头中已经有Authorization,则保持不变;如果没有,则使用URL中的token(如果有的话)构造Authorization头。4.如何测试这个配置?答:可以使用curl命令测试,例如:```bashcurl"http://example.com/path?token=my_token"```然后在后端服务器查看接收到的请求头中是否有`Authorization:Bearermy_token`。也可以使用Nginx的日志功能记录请求头,但注意默认日志不记录请求头,需要配置。总结:根据具体需求选择配置。我们提供了基本配置和更高级的配置(保留原有请求头)。</think>### 如何将URL中的token参数移动到Nginx请求头中 在Nginx中,可以通过以下步骤将URL中的`token`参数提取并添加到HTTP请求头中(例如`Authorization`头): #### 解决方案 ```nginx server { listen 80; server_name your-domain.com; location / { # 提取URL中的token参数值 set $auth_token $arg_token; # 将token添加到请求头(Bearer模式) proxy_set_header Authorization "Bearer $auth_token"; # 代理到后端服务器 proxy_pass http://backend-server; # 可选:移除URL中的token参数(避免泄露) if ($args ~* "(.*)&?token=[^&]*(.*)") { set $args $1$2; } } } ``` #### 关键配置说明: 1. **提取URL参数** `set $auth_token $arg_token;`: 使用内置变量`$arg_token`捕获URL中的`?token=xxx`参数值。 2. **添加到请求头** `proxy_set_header Authorization "Bearer $auth_token";`: 将token值按`Bearer`方案添加到`Authorization`头,后端可通过标准头获取认证信息。 3. **移除URL参数(可选)** 正则表达式`(.*)&?token=[^&]*(.*)`: 匹配并删除URL中的`token`参数,避免敏感信息出现在日志或浏览器地址栏。 #### 验证方法 使用curl测试配置: ```bash curl "http://your-domain.com/api?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" ``` 后端将收到请求头: `Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9` #### 注意事项 1. **安全性** - 建议配合HTTPS使用,防止token被截获 - 敏感操作应使用短时效token - 移除URL参数可降低泄露风险[^1] 2. **性能优化** - 对静态文件跳过处理(避免不必要的正则匹配): ```nginx location ~* \.(js|css|png)$ { # 不处理静态文件的token proxy_pass http://backend-server; } ``` 3. **多参数处理** 若需同时处理多个参数(如`token`和`appId`): ```nginx set $auth_header "Bearer $arg_token"; if ($arg_appId) { set $auth_header "${auth_header} AppId=$arg_appId"; } proxy_set_header X-Auth $auth_header; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值