企业代理下CURL摘要认证URI不匹配致400错误的解决咨询
问题描述
我尝试用curl通过企业代理访问需要摘要认证(Digest Authentication)的远程主机,执行的curl命令如下:
curl -x "http://proxy_username:proxy_pass@proxyIp.xxx.xxx.xxx:8080" -L -X GET "https://remote-host.something.com:443/tomcat_servlet/UploadServlet" --digest -u digest_auth_user:digest_auth_pass -v -k
但收到Apache HTTPD返回的400 Bad Request错误,curl完整输出如下:
* Trying proxyIp.xxx.xxx.xxx:8080... * Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0) * allocate connect buffer * Establish HTTP proxy tunnel to remote-host.something.com:443 * Proxy auth using Basic with user 'proxy_username' * Server auth using Digest with user 'digest_auth_user' > CONNECT remote-host.something.com:443 HTTP/1.1 > Host: remote-host.something.com:443 > Proxy-Authorization: Basic <redacted> > User-Agent: curl/7.83.1 > Proxy-Connection: Keep-Alive > < HTTP/1.1 200 Connection established < Via:HTTP/1.1 s_proxy_nrt < * Proxy replied 200 to CONNECT request * CONNECT phase completed * schannel: disabled automatic use of client certificate * ALPN: offers http/1.1 * ALPN: server did not agree on a protocol. Uses default. * Server auth using Digest with user 'digest_auth_user' > GET /tomcat_servlet/UploadServlet HTTP/1.1 > Host: remote-host.something.com > User-Agent: curl/7.83.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 307 Temporary Redirect < Server: Cisco Umbrella < Date: Tue, 14 Feb 2023 02:52:03 GMT < Content-Type: text/html < Content-Length: 190 < Connection: keep-alive < Set-Cookie: swg_https_a2bc=1; Path=/; Expires=Tue, 14-Feb-23 03:02:03 GMT; domain=remote-host.something.com; SameSite=None; Secure < Location: https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1 < Via: HTTP/1.1 s_proxy_nrt < * Ignoring the response-body * Connection #0 to host proxyIp.xxx.xxx.xxx left intact * Issue another request to this URL: 'https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1' * Found bundle for host: 0x1a0ed47d970 [serially] * Re-using existing connection #0 with proxy proxyIp.xxx.xxx.xxx * Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0) * Server auth using Digest with user 'digest_auth_user' > GET /tomcat_servlet/UploadServlet?swg_a2bc=1 HTTP/1.1 > Host: remote-host.something.com > User-Agent: curl/7.83.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 401 Unauthorized < Date: Tue, 14 Feb 2023 02:52:03 GMT < Content-Type: text/html; charset=iso-8859-1 < Content-Length: 381 < Connection: keep-alive < Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1k < WWW-Authenticate: Digest realm="https_transfer", nonce="redacted", algorithm=MD5, qop="auth" < Via: HTTP/1.1 m_proxy_nrt < * Ignoring the response-body * Connection #0 to host proxyIp.xxx.xxx.xxx left intact * Issue another request to this URL: 'https://remote-host.something.com/tomcat_servlet/UploadServlet?swg_a2bc=1' * Found bundle for host: 0x1a0ed47d970 [serially] * Re-using existing connection #0 with proxy proxyIp.xxx.xxx.xxx * Connected to proxyIp.xxx.xxx.xxx (proxyIp.xxx.xxx.xxx) port 8080 (#0) * Server auth using Digest with user 'digest_auth_user' > GET /tomcat_servlet/UploadServlet?swg_a2bc=1 HTTP/1.1 > Host: remote-host.something.com > Authorization: Digest username="digest_auth_user",realm="https_transfer",nonce="redacted",uri="/tomcat_servlet/UploadServlet?swg_a2bc=1",cnonce="redacted",nc=00000001,algorithm=MD5,response="redacted",qop="redacted" > User-Agent: curl/7.83.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 400 Bad Request < Date: Tue, 14 Feb 2023 02:52:03 GMT < Content-Type: text/html; charset=iso-8859-1 < Content-Length: 226 < Connection: keep-alive < Server: Apache/2.4.48 (Win64) OpenSSL/1.1.1k < Via: HTTP/1.1 m_proxy_nrt < <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>400 Bad Request</title> </head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> </p> </body></html> * Connection #0 to host proxyIp.xxx.xxx.xxx left intact
服务器端HTTPD日志显示:
[auth_digest:error] [pid 3052:tid 1928] [client xxx.xxx.xxx.xxx:xxx] AH01786: uri mismatch - </tomcat_servlet/UploadServlet?swg_a2bc=1> does not match request-uri </tomcat_servlet/UploadServlet>
原因是curl把代理返回的查询参数加入了认证头的URI中,导致和服务器端的请求URI不匹配。当前HTTPD配置如下:
<Location /tomcat_servlet> ProxyPass http://localhost:8080/tomcat_servlet ProxyPassReverse http://localhost:8080/tomcat_servlet AuthType Digest AuthName https_transfer AuthUserFile ${SRVROOT}/conf/.htpasswd Require valid-user </Location>
解决方案
方案一:调整curl命令
如果你的curl版本在7.75.0及以上,可以用--digest-uri参数强制指定认证头中的URI为原始路径,忽略跳转后的查询参数:
curl -x "http://proxy_username:proxy_pass@proxyIp.xxx.xxx.xxx:8080" -L -X GET "https://remote-host.something.com:443/tomcat_servlet/UploadServlet" --digest -u digest_auth_user:digest_auth_pass --digest-uri "/tomcat_servlet/UploadServlet" -v -k
若curl版本较低不支持该参数,建议优先升级curl;也可以手动构造Authorization头,但操作繁琐不推荐。
方案二:修改Apache HTTPD配置
在<Location>块中添加AuthDigestEnableQueryStringHashing Off,让Apache计算摘要认证时忽略查询字符串:
<Location /tomcat_servlet> ProxyPass http://localhost:8080/tomcat_servlet ProxyPassReverse http://localhost:8080/tomcat_servlet AuthType Digest AuthName https_transfer AuthUserFile ${SRVROOT}/conf/.htpasswd AuthDigestEnableQueryStringHashing Off Require valid-user </Location>
修改后重启Apache服务即可生效。
内容的提问来源于stack exchange,提问作者Mirza Prangon
相关产品推荐
相关产品推荐

