删除“ www”。从请求URI
,如果请求URI是“ http”,则重定向到“ https”。
有很多示例,分别说明了如何分别执行这些操作,但是我不知道提出一种解决方案,该解决方案可以正确执行这两种操作(即不会创建重定向循环并正确处理所有情况)。
它需要处理以下所有情况:
1. http://www.example.com/path
2. https://www.example.com/path
3. http://example.com/path
4. https://example.com/path
这些都应该以https://example.com/path(#4)结尾而不循环。有什么想法吗?
#1 楼
实现此目的的最佳方法是使用三个服务器块:一个将http重定向到https,一个将https www-name重定向到no-www,以及一个实际处理请求的服务器。使用额外的服务器块而不是ifs的原因是,使用哈希表执行服务器选择非常快。使用服务器级的if意味着对每个请求都运行if,这很浪费。另外,在重写中捕获请求的uri是浪费的,因为nginx已经在$ uri和$ request_uri变量中分别具有此信息(分别不带查询字符串和带查询字符串)。server {
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /path/to/server.cert;
ssl_certificate_key /path/to/server.key;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /path/to/server.cert;
ssl_certificate_key /path/to/server.key;
server_name example.com;
<locations for processing requests>
}
评论
中间块是否必要?第一个块是否已经从www重写为非www?
– pbreitenbach
2011年5月16日20:39
第一个块仅处理http。中间的块是将https请求从https:// www.example.com/重定向到https:// example.com/所必需的。 (对不起,多余的空格,否则我无法显示https)
– kolbyjack
2011年5月17日在1:03
只是一个较小的格式说明-如果您要避免建立链接,可以将注释文本放在反引号`中,即在波浪号下。它将显示为:https://example.com/
–独眼巨人
2011年6月9日在21:13
第二个区块也需要证书信息。
–ricka
16年5月6日在1:20
尝试这个答案,我遇到了另一个问题。以为我可以将301从www.sub.example.com重定向到sub.example.com,然后仅获取sub.example.com的SSL证书现在,我知道ssl证书检查发生在301重定向之前,因此它无法工作。此处提供更多说明:serverfault.com/a/358625/144811
–烦恼
16年11月24日在18:08
#2 楼
这对我有用:server {
listen 80;
server_name www.yourdomain.com yourdomain.com;
return 301 https://yourdomain.com$request_uri;
}
server {
listen 443 ssl;
server_name www.yourdomain.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private/key.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
return 301 https://yourdomain.com$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private/key.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# do the proper handling of the request
}
请记住,
yourdomain.com
和www.yourdomain.com
都必须在您的SSL证书中。使用通配符证书或服务器备用名称(如此处所述)是可行的。在https://www.startssl.com上查看执行此操作的漂亮且免费的证书。 (伊迪丝:从Chrome版本56开始,不再受信任startssl证书。请改用https://letsencrypt.org/。)评论
这实际上是可行的,但我认为可以以更清晰的方式完成,而无需大量重复的配置行。
– zloynemec
17年9月18日在8:48
@zloynemec您可以将SSL内容放入单独的.conf文件中,并使用include规则将其添加到两个SSL服务器块中。
–Igettäjä
18年4月2日在9:03
另外,如果您使用cloudflare,则需要支付$ 10 /月的证书才能重定向和代理2个子域(www + something)。让我知道是否有解决方法。
– Freedo
18-09-24在4:17
#3 楼
在花了很多时间处理数百个类似案例之后,我提出了以下代码段。它很短,可以很容易地调整以适合任何东西。server {
listen 80;
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /path/to/my/certs/example.com/fullchain.pem;
ssl_certificate_key /path/to/my/certs/example.com/privkey.pem;
# Redirect to the correct place, if needed
set $https_redirect 0;
if ($server_port = 80) { set $https_redirect 1; }
if ($host ~ '^www\.') { set $https_redirect 1; }
if ($https_redirect = 1) {
return 301 https://example.com$request_uri;
}
location / {
# ...
}
哦,但是
if
是邪恶的!是的,可以。但是它的存在是有原因的,对那些知道如何正确使用它的人来说应该不会造成伤害。 ;)
评论
我喜欢这个,但是您是否有任何有关性能提升的数据?谢谢!
– Freedo
18-09-24在4:17
老实说,我从来没有做过基准测试,但我相信与单独的规则相比几乎不会产生影响,因为其效果几乎相同。
– emyller
18-09-24在20:38
重定向基准?这不是真的相关吗? (真实的问题,而不是巨魔^^)
–矩阵
18-11-23在4:42
#4 楼
我更喜欢返回一个响应代码,以便浏览器知道您将其重定向到另一个URL。server {
listen 80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
,然后另一个服务器配置块用于
https
server {
listen 443 ssl;
server_name example.com;
...
}
#5 楼
为此目的如何创建服务器块:server{
listen 80;
server_name www.example.net example.net;
rewrite ^(.*) https://example.net permanent;
}
,然后重新启动nginx
评论
重新启动时出现“服务器名冲突”错误。另外,该命令不会在端口443上侦听SSL,我还需要担心将https://www.example.com重定向到https://example.com。
–德文
2011年4月11日在16:56
#6 楼
我认为这应该可行。在普通的HTTP服务器定义上,建议使用类似anthonysomerset的名称,即:
rewrite ^(.*) https://example.net permanent;
然后在SSL服务器上定义:
if ($host ~ /^www\./) {
rewrite ^(.*) https://example.net permanent;
}
这样,无论用户最初访问哪个URL,重定向都应仅对每个请求执行一次。
评论
很好,谢谢。我不得不将您的条件更改为if($ host ='www.example.com'){因为您的正则表达式对我不起作用。不知道为什么,因为它看起来正确。
–德文
2011年4月11日18:20
请注意,如果是邪恶的,通常最好使用声明性方式。
–布莱斯(Blaise)
15年3月21日在6:35
#7 楼
这是最终为我工作的完整示例。问题是我在www重定向块中没有ssl详细信息(ssl_certificate
等)。记住要检查您的日志(sudo tail -f /var/log/nginx/error.log
)!# HTTP — redirect all traffic to HTTPS
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
return 301 https://$host$request_uri;
}
# HTTPS — redirects www to non-www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
# Use the Let's Encrypt certificates
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Include the SSL configuration from cipherli.st
include snippets/ssl-params.conf;
return 301 https://example.com$request_uri;
}
# HTTPS — proxy all requests to the app (port 3001)
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com sub.example.com;
# Use the Let's Encrypt certificates
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Include the SSL configuration from cipherli.st
include snippets/ssl-params.conf;
# For LetsEncrypt:
location ~ /.well-known {
root /var/www/html;
allow all;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3001;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
评论
我只是在DNS级别将www.mydomain.com重定向到mydomain.com,并在nginx中将301(非https)添加到https。似乎应该是¯\ _(ツ)_ /¯