nginx配置http强制跳转https

很多网站虽然支持 https, 但是直接在浏览器地址栏输入网址后, 默认仍是以 http 协议去访问的, http 强制跳转 https 的需求应运而生, 以下介绍三种实现的方式

rewrite 方法

这是最常用的实现方法, 将所有 http 请求通过 rewrite 重定向到 https 即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {  
listen 80;
server_name docs.lvrui.io

rewrite ^(.*)$ https://$host$1 permanent;
}

server {
listen 443 ssl;
server_name docs.lvrui.io;
index index.html index.htm;
access_log /var/log/nginx/docs.log main;
ssl on;
ssl_certificate /etc/ssl/docs.20150509.cn.crt;
ssl_certificate_key /etc/ssl/docs.20150509.cn.key;
error_page 404 /404.html;
location / {
root /var/www/html/docs;
}
}

497 状态码

error code 497: normal request was sent to HTTPS

在一个站点只允许 https 访问时, 如果使用 http 访问会报出497错误码

利用497状态码重定向到 https

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
server_name docs.lvrui.io

error_page 497 https://$host$uri?$args;
}

server {
listen 443 ssl;
server_name docs.lvrui.io;
index index.html index.htm;
access_log /var/log/nginx/docs.log main;
ssl on;
ssl_certificate /etc/ssl/docs.20150509.cn.crt;
ssl_certificate_key /etc/ssl/docs.20150509.cn.key;
error_page 404 /404.html;
location / {
root /var/www/html/docs;
}
}

index.html 刷新网页

上面两种方法均会耗费服务器资源, 我们使用 curl 来看下百度是如何实现的 baidu.comwww.baidu.com 的跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ curl baidu.com -vv 
* Rebuilt URL to: baidu.com/
* Trying 220.181.57.217...
* TCP_NODELAY set
* Connected to baidu.com (220.181.57.217) port 80 (#0)
> GET / HTTP/1.1
> Host: baidu.com
> User-Agent: curl/7.51.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 01 Apr 2017 06:32:35 GMT
< Server: Apache
< Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
< ETag: "51-47cf7e6ee8400"
< Accept-Ranges: bytes
< Content-Length: 81
< Cache-Control: max-age=86400
< Expires: Sun, 02 Apr 2017 06:32:35 GMT
< Connection: Keep-Alive
< Content-Type: text/html
<
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>
* Curl_http_done: called premature == 0
* Connection #0 to host baidu.com left intact

可以看到百度很巧妙的利用meta的刷新作用,将baidu.com跳转到www.baidu.com

同理, 我们也可以用这个特性来实现 http 向 https 的跳转

1
2
3
4
# index.html
<html>
<meta http-equiv="refresh" content="0;url=https://docs.lvrui.io/">
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name docs.lvrui.io;

location / {
# 将 index.html 文件放到下面的目录下
root /var/www/html/refresh/;
}
}

server {
listen 443 ssl;
server_name docs.lvrui.io;
index index.html index.htm;
access_log /var/log/nginx/docs.log main;
ssl on;
ssl_certificate /etc/ssl/docs.20150509.cn.crt;
ssl_certificate_key /etc/ssl/docs.20150509.cn.key;
error_page 404 /404.html;
location / {
root /var/www/html/docs;
}
}