Nginx

nginx try_files 在負載均衡器後面發出 http 重定向;需要https

  • March 11, 2019

我的 nginx 實例位於 SSL 終止的負載均衡器後面,我希望所有 url 都命中https端點,這意味著http被重定向到https.

當 url 有一個斜杠時,一切都很好。他們都得到很好的重定向:

#!/bin/sh

do_curl() {
  echo "\n$ do_curl $1"
  curl -L -s -D - "$1" -o /dev/null | grep -iE 'Location|HTTP/|server'
}

$ do_curl https://example.com/
HTTP/2 200

$ do_curl http://example.com/foo/
HTTP/1.1 301 Moved Permanently
Location: https://example.com/foo/
HTTP/2 200

$ do_curl https://example.com/foo/
HTTP/2 200

但是當相同的 url 沒有斜杠時,nginxtry_files似乎http總是發出重定向: bad.png

這是我的 nginx vhost.conf

server {
   listen 80;
   root /app/;
   index index.html index.htm;

   # This 'if' block is only needed because my SSL-terminated Load balancer proxies both http and https to nginx.
   # If my Load balancer only proxied https to nginx, and dropped http, this 'if' block can be omitted.
   if ($http_x_forwarded_proto = "http") {
       return 301 https://$host$request_uri;
   }

   location / {
       try_files $uri $uri/ =404;
   }
}

如何讓 nginx在遇到參數(上面的第二個參數)並成功找到匹配的文件(上面的 nginx 配置中的指令定義的位置)時try_files直接重定向?https $scheme``$uri/``try_files``$uri/<index>``index``index

我搜尋了類似的問題,例如這裡這里這裡,但仍然找不到任何相關的東西。

正如@Florin 在問題的評論中指出的那樣,try_files只執行重寫。所以我回過頭來省略了try_files我的塊vhost.conf,真的,我得到了同樣的行為,沒有尾隨斜杠https的url被重定向到它的尾隨對應物。http

解決方案

相反,我的問題標題應該更像是“如何防止 nginx 從 HTTPS 重定向到 HTTP”,這將是如何防止 nginx 在 AWS 上從 HTTPS 重定向到 HTTP 的重複問題?@Richard 在他對我的問題的評論中指出,他回答了。

巧合的是,我的情況和問題實際上與那個問題中的相同。在他的回答中,@Richard 指出,緩解 nginx 假設與$scheme請求者相同(即 SSL 終止負載均衡器)的問題的最佳方法是在負載均衡器點的標頭中替換httpwith ,這對我來說是不可能的。然後,他繼續描述了在執行重定向時的三種方式。https``Location``$scheme``https

在這三種解決方案中,對我有用的一種是使用absolute_redirect off;. 這可以防止 nginx 使用$scheme它在重定向中使用的錯誤。

現在,我vhost.conf只需要:

server {
   listen 80;
   root /app/;
   index index.html index.htm;

   absolute_redirect off;

   # This 'if' block is only needed because my SSL-terminated Load balancer proxies both http and https to nginx.
   # If my Load balancer only proxied https to nginx, and dropped http, this 'if' block can be omitted.
   if ($http_x_forwarded_proto = "http") {
       return 301 https://$host$request_uri;
   }
}

引用自:https://serverfault.com/questions/955730