Nginx:在 https 上将非 www 重定向到 www

Posted

技术标签:

【中文标题】Nginx:在 https 上将非 www 重定向到 www【英文标题】:Nginx: redirect non-www to www on https 【发布时间】:2014-05-12 14:40:17 【问题描述】:

如果我在 https 上,nginx 无法将非 www 重定向到 www:

https://domain.com 到 https://www.domain.com

我在.conf 中的当前设置是:

server 
  listen 80;
  server_name www.domain.com domain.com;
  return 301 https://www.domain.com$request_uri;

server 
  listen 443;
  server_name domain.com;
  return 301 https://www.domain.com$request_uri;

server 
  listen IP_ADDRESS:443 ssl;
  server_name www.domain.com;
  ...

http://domain.com 到 https://www.domain.com 和 http://www.domain 到 https://www.domain.com 有效,但 https 上的非 www 到 www 无效。

如果我在第二个 server 块上添加 IP_ADDRESS,我会在 Chrome 中收到错误(SSL 错误),并且(www 和非 www)都停止工作。

更新:

感谢 Steffen(以下回答),我将自签名证书更新为 *.domain.com 而不是 domain.com

.conf 文件已更新为以下格式:

ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;

server 
  listen 80;
  server_name www.domain.com domain.com;
  return 301 https://www.domain.com$request_uri;

server 
  listen 443 ssl;
  server_name domain.com;
  return 301 https://www.domain.com$request_uri;

server 
  listen 443 ssl;
  server_name www.domain.com;
  ...

【问题讨论】:

还要确保您的服务器块或更高版本具有 ssl 证书行,以便人们在重定向之前可以实际连接。 【参考方案1】:

这可能是因为您没有 domain.com 的证书,而只有 www.domain.com 或 *.domain.com 的证书。详情请见Nginx redirect http://www and naked http/https to https://www 或https://serverfault.com/questions/579916/nginx-redirect-https-www-to-https-non-www-without-untrusted-connection-warn/579917#579917。

【讨论】:

【参考方案2】:

我有类似的情况,这就是我解决重定向问题的方法

https://example.com -----> https://www.example.com

 server 
      listen        443;
       server_name    example.com;
         if ($host = example.com) 
        rewrite ^(.*) https://www.example.com:443$request_uri? permanent;
      
  

希望这会有所帮助!

Using if condition in nginx

指令如果在位置上下文中使用时出现问题,在某些情况下,它并没有达到您的预期,而是完全不同。在某些情况下,它甚至会出现段错误。如果可能的话,通常最好避免它。如果在位置上下文中,唯一可以在内部完成的 100% 安全的事情是: 返回 ...;重写...最后;

【讨论】:

我已经尝试了 1278361872612 的东西,除了这个,谢谢你,好心的先生。【参考方案3】:

这是我使用的更优雅的解决方案。实际网站需要一个服务器块,从非 www/non-https 重定向到 https://www.* 需要一个服务器块。

server 
  listen IP_ADDRESS:443 ssl;
  server_name www.domain.com;

server 
  listen IP_ADDRESS:80 ssl default_server;
  listen IP_ADDRESS:443 ssl default_server;
  return 301 https://www.domain.com$request_uri;

default_server 选项很重要,否则第一个定义将成为默认值,这可能会违背您重定向除www.domain.com 之外的所有请求的意图。通过使用 default_server,您的重定向服务器块充当一个包罗万象的功能。

不过,在我看来,您不应该使用“www”。您应该从 www 重定向到非 www。 www 是当今无关紧要的传统事物。通过从非 www 重定向到 www,您正在延续这种无关紧要的遗产。

【讨论】:

【参考方案4】:

在第二个服务器块(以“listen 443;”开头)中,您必须添加 SSL 服务器组(最后一个组)中的所有与 SSL 相关的指令。这是我的 example.conf:

server 
    listen 80;
    server_name example.com www.example.com;
    return 301 https://www.$server_name$request_uri;


server 
    listen 443 ssl;
    server_name example.com;
    return 301 https://www.$server_name$request_uri;

    # SSL
    ssl on;
    ssl_certificate /var/www/example.com/cert/bundle.cer;
    ssl_certificate_key /var/www/example.com/cert/example.com.key;

    # Enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    # Intermediate cypersuite as recommended by Mozilla
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;
    # Add HSTS (HTTPStrictTransportSecurity)
    add_header Strict-Transport-Security "max-age=31536000";



server 
    listen 443 ssl;
    server_name www.example.com;
    root /var/www/example.com/public;
    index index.html index.htm index.php;
    client_max_body_size 32m;

    access_log  /var/www/example.com/access.log;
    error_log  /var/www/example.com/error.log;

    # SSL
    ssl on;
    ssl_certificate /var/www/example.com/cert/bundle.cer;
    ssl_certificate_key /var/www/example.com/cert/example.com.key;

    # Enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    # Intermediate cypersuite as recommended by Mozilla
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;
    # Add HSTS (HTTPStrictTransportSecurity)
    add_header Strict-Transport-Security "max-age=31536000";

    # Directives to send expires headers and turn off 404 error logging.
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ 
        #expires max;
        log_not_found off;
        access_log off;
    

    location = /favicon.ico 
        log_not_found off;
        access_log off;
    

    location = /robots.txt 
        allow all;
        log_not_found off;
        access_log off;
    

    ## Disable viewing .htaccess & .htpassword
    location ~ /\.ht 
        deny  all;
    

    location ^~ /admin/ 
                auth_basic "Restricted";
                auth_basic_user_file /var/www/example.com/.htpasswd;
                try_files $uri $uri/ /index.php$is_args$args;
                location ~ \.php$ 
                        include /etc/nginx/php-inside.conf;
                
        

    include /etc/nginx/php.conf;

【讨论】:

【参考方案5】:

我在两个服务器指令上都使用了 rewrite,它对我有用:

一般重写指令非 www 到 https wwww

 server 
        listen 80;
        server_name example.com www.example.com;
        return 301 https://www.$server_name$request_uri;

非 www 到 https wwww 的 SSL 规则指令

 server 
    listen 443 ssl;
    server_name example.com;
    return 301 https://www.$server_name$request_uri;

【讨论】:

以上是关于Nginx:在 https 上将非 www 重定向到 www的主要内容,如果未能解决你的问题,请参考以下文章

Nginx 重定向(非 www 到 www)不适用于 Certbot

NGINX 将 http 重定向到 https,将非 www 重定向到 ww

将http非www重定向到https非www

https 非 www 重定向

Nginx:将非www重定向到www https

在 Flask+Heroku 上将 HTTP 重定向到 HTTPS