使用 Nginx 通过 SSL 将非 www 重定向到 www

使用 Nginx 通过 SSL 将非 www 重定向到 www

我在尝试重定向时遇到错误https://example.comhttps://www.example.com

当我去https://example.com,它不会重定向并返回 page/200 状态。

我不想要这个,我想让它重定向到https://www.example.com

当我去http://example.com,它会重定向到https://www.example.com

有人能告诉我哪里错了吗?

这是我的默认和默认 ssl 配置文件:

默认配置文件

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

默认 SSL 配置文件

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}
server {
    server_name www.example.com;

    listen 443;
    root /home/app/myproject/current/public;
    index index.html index.htm;

    error_log /srv/www/example.com/logs/error.log info;
    access_log /srv/www/example.com/logs/access.log combined;

    ssl on;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
    ssl_prefer_server_ciphers on;

    client_max_body_size 20M;


    try_files $uri/index.html $uri.html $uri @app;


    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

答案1

listen文件中缺少指令default-ssl.conf。添加listen 443;此指令

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

默认情况下,如果省略此指令,nginx 会假定您想要监听端口 80。这是文档此默认行为。


编辑:感谢@TeroKilkanen 的评论。

这是 default-ssl.conf 的完整配置

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /srv/www/example.com/keys/ssl.crt;
    ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
    return 301 https://www.example.com$request_uri;
}

边注:你可以用以下建议替换ssl on;指令:listen 443 ssl;nginx 文档

答案2

只需添加一个 if 语句,您就可以开始工作了。我在 curl.exe -I 中检查了结果,除了https://www.example.com被视为 301。SSL 比较棘手,因为它会在您获得 301 URL 重定向之前进行检查。因此,您会收到证书错误。

就我个人而言,我喜欢从域中删除 www,但我在下面写了代码来回答您的问题。

server {
listen 443 ssl;
listen [::]:443 ssl; # IPV6

server_name example.com www.example.com; # List all variations here

# If the domain is https://example.com, lets fix it!

if ($host = 'example.com') {
  return 301 https://www.example.com$request_uri;
}

# If the domain is https://www.example.com, it's OK! No changes necessary!

... # SSL .pem stuff
...
}

server {
  listen 80;
  listen [::]:80;

  # If the domain is http://example.com or http://www.example.com, then let's change it to https!

  server_name example.com www.example.com;
  return 301 https://www.example.com$request_uri;
}

答案3

我这样做的方式是在 ssl 服务器块中使用 if 语句,重定向到 www 的 https

ssl_certificate /srv/www/example.com/keys/ssl.crt;
ssl_certificate_key /srv/www/example.com/keys/www.example.com.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AES128-SHA:RC4-MD5:ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:RSA+3DES:!ADH:!AECDH:!MD5:AES128-SHA;
ssl_prefer_server_ciphers on;
client_max_body_size 20M;

upstream app_server_ssl {
    server unix:/tmp/unicorn.sock fail_timeout=0;
}

server {
    server_name example.com;
    return 301 https://www.example.com$request_uri
}

server {
    listen 443 default_server ssl;
    server_name www.example.com;

    # redirect https://example.com to https://www.example.com
    # mainly for SEO purposes etc
    #we will use a variable to do that
    set $redirect_var 0;

    if ($host = 'example.com') {
      set $redirect_var 1;
    }
    if ($host = 'www.example.com') {
      set $redirect_var 1;
    }

    if ($redirect_var = 1) {
      return 301 https://www.example.com$request_uri;
    } 

    try_files $uri/index.html $uri.html $uri @app;

    # CVE-2013-2028 http://mailman.nginx.org/pipermail/nginx-announce/2013/000112.html
    if ($http_transfer_encoding ~* chunked) {
            return 444;
        }

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server_ssl;
    }

    error_page 500 502 503 504 /500.html;

    location = /500.html {
        root /home/app/example/current/public;
    }
}

当然,每当你想在 nginx 配置文件中使用 if 语句时,你应该已经读过:https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/

答案4

就我而言,重定向自 http://example.comhttps://www.example.com.我像这样用“IF 条件”配置我的 nginx,它对我有用。

  server {
        listen 80;

        server_name example.com;


            if ($host = example.com) {
                    return 301 https://www.$host$request_uri;
            }  


        location / {
            root   html;
            index  index.php index.html index.htm;
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

....

 server {
        server_name www.example.com;
        listen 80;
        return 404;  


 }

相关内容