簡體   English   中英

如何在 NGINX 上將 HTTPS 重定向到 HTTP?

[英]How do I redirect HTTPS to HTTP on NGINX?

有沒有辦法通過在域的 vhost 文件中添加規則來將 HTTPS 請求重定向到 HTTP?

為什么這樣的東西有用? 乍一看,我不確定是否可以完成。 但它提出了一個有趣的問題。

您可以嘗試在配置文件中放置重定向語句並重新啟動服務器。 可能有兩種可能:

  1. 服務器將發出重定向 - 您似乎想要什么。
  2. 服務器將首先進行https交換,然后發出重定向,在這種情況下,有什么意義?

如果我想出更具體的東西,我會添加更多。

更新:(幾個小時后)你可以試試這個。 你需要把它放在你的nginx.conf文件中 -

server {
       listen 443;
       server_name _ *;
       rewrite ^(.*) http://$host$1 permanent;
 }

向客戶端發送永久重定向。 我假設您對 https 使用端口 443(默認)。

server {
    listen      80;
    server_name _ *;
    ...
}

添加此項,以便您在端口 80 上的正常 http 請求不受干擾。

更新:2016年12月18日- server_name _應該用來代替server_name _ *在nginx的版本> 0.6.25(感謝@Luca Steeb)

rewriteif應該避免使用 Nginx。 著名的一句話是,“Nginx 不是 Apache”:換句話說,Nginx 有比重寫更好的方法來處理 URL。 return在技​​術上仍然是 rewrite 模塊的一部分,但它不承擔rewrite的開銷,也不像if那樣充滿警告。

Nginx 有一整頁關於為什么if是 "evil" 它還提供了一個建設性的頁面,解釋為什么要rewriteif是壞的,以及如何解決它。 以下是該頁面關於rewriteif

這是一種錯誤、繁瑣且無效的方式。

您可以使用return正確解決此問題:

server {
    listen 443 ssl;

    # You will need a wildcard certificate if you want to specify multiple
    # hostnames here.
    server_name domain.example www.domain.example;

    # If you have a certificate that is shared among several servers, you
    # can move these outside the `server` block.
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/cert.key;

    # 301          indicates a permanent redirect.  If your redirect is
    #              temporary, you can change it to 302 or omit the number
    #              altogether.
    # $http_host   is the hostname and, if applicable, port--unlike $host,
    #              which will break on non-standard ports
    # $request_uri is the raw URI requested by the client, including any
    #              querystring
    return 301 http://$http_host$request_uri;
}

如果您期望很多機器人不發送Host標頭,只要您堅持使用端口 80 和 443,您就可以使用$host而不是$http_host 。否則,您將需要動態填充$http_host替代品。 盡管使用if ,但只要此代碼出現在server的根目錄中(而不是location塊中),它就是高效且安全的。 但是,您需要使用默認服務器才能適用,這應該避免使用 https。

set $request_host $server_name:$server_port;
if ($http_host) {
    set $request_host $http_host;
}

如果您想對特定路徑強制執行 SSL/TLS,但否則禁止:

server {
    listen 443 ssl;
    server_name domain.example;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/cert.key;

    location / {
        return 301 http://$host$request_uri;
    }

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

server {
    listen 80;
    server_name domain.example;

    location / {
        try_files $uri =404;
    }

    location /secure/ {
        return 301 https://$http_host$request_uri;
    }
}

如果你的服務器沒有與客戶端直接通信——例如,如果你使用 CloudFlare——事情會變得有點復雜。 您需要確保與客戶端直接通信的任何服務器向請求添加適當的X-Forwarded-Proto標頭。

使用這個是一個混亂的提議; 有關完整說明,請參閱IfIsEvil 為了使它有用,由於各種復雜的原因, if塊不能位於location塊內。 這會強制使用rewrite進行 URI 測試。 簡而言之,如果您必須在生產服務器上使用它......不要。 可以這樣想:如果您已經超越了 Apache,那么您已經超越了這個解決方案。

/secure、/secure/ 和 /secure/ 中的任何內容都將強制使用 https,而所有其他 URI 將強制使用 http。 (?! ) PCRE 構造是一個否定的前瞻斷言 (?: ) :)是一個非捕獲組

server {
    # If you're using https between servers, you'll need to modify the listen
    # block and ensure that proper ssl_* statements are either present or
    # inherited.
    listen 80;
    server_name domain.example;

    if ($http_x_forwarded_proto = https) {
        rewrite ^(?!/secure)/ http://$http_host$request_uri? permanent;
    }
    if ($http_x_forwarded_proto != https) {
        rewrite ^/secure(?:/|$) https://$http_host$request_uri? permanent;
    }
}
location / {
    if ($scheme = https) {
        rewrite ^(.*)? http://$http_host$1 permanent;
    }
}

這個問題更適合 serverfault.com 站點。

重定向到 http 的更好方法:

server {
   listen 443;
   return 301 http://$host$request_uri;
}

這避免了重寫中的“if”子句和正則表達式,這些都是迄今為止其他解決方案的特征。 兩者都有性能影響,但在實踐中你必須有相當多的流量才重要。

根據您的設置,您可能還想在 listen 子句中指定一個 ip,也許還需要在上面的 servername 子句中指定。 照原樣,它將適用於所有域名的所有端口 443 請求。 您通常希望每個域都有一個帶有 https 的 IP,因此將上述內容綁定到 IP 比將其綁定到域名更重要,但也有一些變化,例如所有域都是一個域的子域。

編輯:TLS 現在接近於通用,並且有了它的服務器名稱標識 (SNI),它允許多個域上的 HTTPS 站點共享一個 IP。 有一個很好的寫了這里

這幫助了我:

server {
    listen 443;
    server_name server.org www.server.org;
    rewrite ^ http://$server_name$request_uri? permanent;
}

不是一個合適的解決方案,但我能夠通過使用 Cloudflare 解決我的用例,它透明地為我處理 SSL。

唯一的簡單規則已經在我上面的帖子中解釋過:

server {
    listen ip:443;
    server_name www.example.com;
    rewrite ^(.*) http://$host$1 permanent;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM