V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
miao
V2EX  ›  NGINX

NGINX 如何强制 http 301 跳转到 https 网上的教程都是错误的

  •  
  •   miao · 2015-08-21 17:25:52 +08:00 · 27942 次点击
    这是一个创建于 3407 天前的主题,其中的信息可能已经有所发展或是发生改变。
    诸如
    rewrite ^(.*)$ https://$host$1 permanent;
    error_page 497 https://$host$uri?$args;
    等规则试验了都不行
    都会导致循环重定向
    28 条回复    2020-02-05 19:04:34 +08:00
    closeid
        1
    closeid  
       2015-08-21 17:33:47 +08:00   ❤️ 1
    如果使用上面两句,需要 http 和 https 独立成两个 server 。
    SourceMan
        2
    SourceMan  
       2015-08-21 17:42:02 +08:00   ❤️ 1
    server {
    listen 80;
    server_name xxx.com www.xxx.com;
    rewrite ^(.*) https://xxx.com$1 permanent;
    }
    sy1989
        3
    sy1989  
       2015-08-21 17:42:35 +08:00   ❤️ 1
    if ($scheme = http ) {
    rewrite ^(.*)$ https://$host$1 permanent;
    }
    Jat001
        4
    Jat001  
       2015-08-21 17:44:52 +08:00   ❤️ 2
    listen 80;
    listen 443 ssl;

    #下面两个一样的效果
    if ($scheme = http ) {
    return 301 https://$host$request_uri;
    }

    if ($server_port = 80 ) {
    return 301 https://$host$request_uri;
    }

    #http://nginx.org/en/docs/http/ngx_http_ssl_module.html#errors
    error_page 497 https://$host$request_uri;
    Pastsong
        5
    Pastsong  
       2015-08-21 17:45:15 +08:00   ❤️ 1
    listen 80;
    listen 443;

    if ($ssl_protocol = "") { rewrite ^ https://$server_name$request_uri? permanent; }
    virusdefender
        6
    virusdefender  
       2015-08-21 17:55:47 +08:00   ❤️ 2
    server{
    listen 80;
    server_name virusdfefender.net;
    return 301 https://virusdefender.net$request_uri;
    }


    server {
    listen 443 ssl spdy;
    ssl on;
    server_name virusdfefender.net;
    ....
    }
    TankyWoo
        7
    TankyWoo  
       2015-08-21 18:28:43 +08:00   ❤️ 1
    看标题还以为楼主发现了一个惊天 bug ,然后给出一个完美的配置方案

    结果 ~~~

    楼主有质疑精神是好事,但是你想想那么多人都是那么配的,有问题的概率还是比较小啊。你怎么就能这么果断的下结论呢?

    我是直接写了两个 server, 然后一个 rewrite 做 301
    lhbc
        8
    lhbc  
       2015-08-21 18:47:26 +08:00   ❤️ 1
    必须两个 server
    如果只用一个 server ,然后用 if 判断协议或者端口
    每个请求都必须执行一次 if ,这多蛋疼
    salmon5
        9
    salmon5  
       2015-08-21 19:01:57 +08:00   ❤️ 1
    官方推荐 return 301,rewrite 复杂而且性能差。
    ryd994
        10
    ryd994  
       2015-08-21 20:15:38 +08:00   ❤️ 1
    @Jat001
    @sy1989
    @Pastsong
    if is evil,
    明明 return 就好,rewrite 什么,没事 regex 很好玩么?
    mchl
        11
    mchl  
       2015-08-21 20:17:12 +08:00 via Android   ❤️ 1
    error_page 497 https://$server_name:$server_port$request_uri;
    以上是从配置文件里直接粘贴出来的,版本 1.8.0
    shierji
        12
    shierji  
       2015-08-21 20:33:52 +08:00   ❤️ 1
    本来想回的。。不过上面都说的很好了。。
    Bardon
        13
    Bardon  
       2015-08-21 23:11:38 +08:00
    @mchl
    不懂,以下语句写入 443 的那个 server 中
    error_page 497 https://$server_name:$server_port$request_uri;
    告诉我, 80 那个端口怎么知道 497 状态?

    curl 测试
    $ curl -IL http://domain.com
    curl: (7 ) Failed to connect to domain.com port 80: Connection refused
    mchl
        14
    mchl  
       2015-08-21 23:17:27 +08:00 via Android
    @Bardon 哦,要把 listen 80 一行删掉,既然强制跳转 ssl ,为何还要 listen 80
    mchl
        15
    mchl  
       2015-08-21 23:18:39 +08:00 via Android
    @mchl 只要一个 server 配置
    Bardon
        16
    Bardon  
       2015-08-21 23:28:40 +08:00
    @mchl 既然没有 listen 80;
    但 http 默认为 80
    curl 实测结果就是
    curl: (7 ) Failed to connect to domain.com port 80: Connection refused
    Bardon
        17
    Bardon  
       2015-08-21 23:32:06 +08:00
    @mchl 我测试的结果是
    listen 443 spdy;
    listen 80;
    server_name domain.com;
    ......

    error_page 497 https://$server_name:443$request_uri;

    这样才行,必须告诉 nginx ,该域名的 80 端口也能访问进来
    mchl
        18
    mchl  
       2015-08-21 23:37:46 +08:00 via Android
    @Bardon 好吧,我这边网址比较特殊,端口不是默认的 80 和 443 ,访问网址必须指定端口, sorry
    lzxgh621
        19
    lzxgh621  
       2015-08-22 00:21:47 +08:00
    if ($server_port = 80 ) {
    return 301 https://$server_name$request_uri;
    }
    if ($scheme = http ) {
    return 301 https://$server_name$request_uri;
    }
    error_page 497 https://$server_name$request_uri;
    lzxgh621
        20
    lzxgh621  
       2015-08-22 00:23:23 +08:00
    单 server 一直正常 除非你的配置方式不是标准的
    RAKE
        21
    RAKE  
       2015-08-22 00:26:41 +08:00
    return 301
    当然有种更变态的方法就是开启 hsts 。。。
    ryd994
        22
    ryd994  
       2015-08-22 23:35:51 +08:00   ❤️ 1
    @Bardon 你贴的配置要工作,还漏了 ssl on;(顺带一提,这也是个已经废弃的选项)
    希望你在复制粘贴前能先 STFW ,而不是祈祷网上随便找来的一段字符能工作。

    如果你已经 Google 过,你应该明白:
    497 是表示客户端用 HTTP 访问了一个应该用 HTTPS 的端口时返回的非标准状态。因此 497 法本身是个非标准&过时的 hack 。要使 497 法生效,就要把 80 端口故意错误的配置成 SSL 端口。这个方法只能挂一个站。

    Again ,对 Nginx ,唯一正解就是两个 server 。 6 楼去掉那行 ssl on 就很好

    @RAKE http 访问时返回的 HSTS 是不生效的,至少 chrome 上是这样

    @lzxgh621 回复前能先读读别人的回复么? if is evil 。何况根本没必要
    Bardon
        23
    Bardon  
       2015-08-22 23:43:25 +08:00
    @ryd994 不懂你什么意思
    我确认我在 google 后,且经过实机测试的结果,你或学没有看到“...... ”,所以激动了?
    如果你认为我只是个复制粘贴党,那么我们没有共同语言
    Bardon
        24
    Bardon  
       2015-08-22 23:44:58 +08:00
    @ryd994 重新看了篇,懂你意思了,分歧在非标准端口上
    我的配置没问题
    usernametoolong
        25
    usernametoolong  
       2015-08-23 09:15:30 +08:00
    3 楼 4 楼已经给了答案
    lazyyz
        26
    lazyyz  
       2015-10-04 16:14:47 +08:00
    开 80 和 443 两个 server ,在 80 里用 return 301 就可以了
    location / {
    return 301 https://你的域名$request_uri;
    }
    q66213772
        27
    q66213772  
       2017-04-10 14:55:00 +08:00
    有只监听一个端口的方法吗?
    t5k5
        28
    t5k5  
       2020-02-05 19:04:34 +08:00
    一个万年老贴帮了我,和楼主遇到一样的问题,重定向放在了同一个 server 导致重定向无法访问。
    后来独立出来一个 server,却也没有生效。
    突然意识到,应该把重定向的 server 放前面 :(
    希望对后面搜索找寻答案的人有点帮助

    server
    {
    listen 80;
    server_name www.domain.com;
    return 301 https://www.domain.com$request_uri;
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1576 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:52 · PVG 00:52 · LAX 08:52 · JFK 11:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.