[英]How do I redirect HTTPS to HTTP on NGINX?
有沒有辦法通過在域的 vhost 文件中添加規則來將 HTTPS 請求重定向到 HTTP?
為什么這樣的東西有用? 乍一看,我不確定是否可以完成。 但它提出了一個有趣的問題。
您可以嘗試在配置文件中放置重定向語句並重新啟動服務器。 可能有兩種可能:
如果我想出更具體的東西,我會添加更多。
更新:(幾個小時后)你可以試試這個。 你需要把它放在你的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)
rewrite
, if
應該避免使用 Nginx。 著名的一句話是,“Nginx 不是 Apache”:換句話說,Nginx 有比重寫更好的方法來處理 URL。 return
在技術上仍然是 rewrite 模塊的一部分,但它不承擔rewrite
的開銷,也不像if
那樣充滿警告。
Nginx 有一整頁關於為什么if
是 "evil" 。 它還提供了一個建設性的頁面,解釋為什么要rewrite
, if
是壞的,以及如何解決它。 以下是該頁面關於rewrite
和if
:
這是一種錯誤、繁瑣且無效的方式。
您可以使用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.