【问题标题】:How do I rewrite / redirect from http to https in Go?如何在 Go 中从 http 重写/重定向到 https?
【发布时间】:2016-05-31 02:38:52
【问题描述】:

我已经设置了 TLS 并且它可以工作。我知道如何在 nginx 中从 http 重写为 https,但我不再使用 nginx。我不知道如何在 Go 中正确执行此操作。

func main() {

    certificate := "/srv/ssl/ssl-bundle.crt"
    privateKey := "/srv/ssl/mykey.key"

    http.HandleFunc("/", rootHander)
    // log.Fatal(http.ListenAndServe(":80", nil))
    log.Fatal(http.ListenAndServeTLS(":443", certificate, privateKey, nil))
}

func rootHander(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("To the moon!"))
}

我该如何以一种好的方式做到这一点?

【问题讨论】:

    标签: go


    【解决方案1】:

    创建一个处理重定向到 https 的处理程序,例如:

    func redirectTLS(w http.ResponseWriter, r *http.Request) {
        http.Redirect(w, r, "https://IPAddr:443"+r.RequestURI, http.StatusMovedPermanently)
    }
    

    然后重定向http流量:

    go func() {
        if err := http.ListenAndServe(":80", http.HandlerFunc(redirectTLS)); err != nil {
            log.Fatalf("ListenAndServe error: %v", err)
        }
    }()
    

    【讨论】:

    • 非常感谢!
    • 对于要重定向到的地址,您最好使用"https://" + r.Host + r.RequestURI,这样可以避免对您的主机名或 IP 地址进行硬编码。
    • r.Host是从http请求中的Host头获取的。我认为它不应该被信任(见this 帖子),r.RequestURI 可能包含像http://localhost:5000 这样的完整来源(见this 帖子)所以它也不应该被信任。
    • TL;DR,尽管用户可能会摆弄,但使用 r.Host 是正确的方法。 --- 有趣的讨论。 @MasBagol 非常正确,用户可以“愚弄”或覆盖 r.Host 。但是,替代方案并不漂亮,这可能意味着要求您的管理员/用户配置“IPAddr”,这是一个坏主意。如果没有很多关于 NAT/requestor-environment 的脆弱假设,那么在不使用 r.Host 的情况下很难弄清楚将什么传递给 http.Redirect()。和!举个例子,“黑客”只是设法让你的 Go-app 将 HTTP 301 Moved Permanently 传回他们自己的浏览器。
    【解决方案2】:

    上面发布的解决方案有点不灵活,尤其是在外部主机名与本地主机不同的情况下。

    这是我用于 HTTP->HTTPS 重定向的代码:

    package main
    
    import (
        "net"
        "log"
        "net/http"
    )
    
    var httpAddr ":8080"
    var httpsAddr ":8443"
    
    func main() {
        srv := http.Server{
            Addr: httpsAddr,
        }
    
        _, tlsPort, err := net.SplitHostPort(httpsAddr)
        if err != nil {
            return err
        }
        go redirectToHTTPS(tlsPort)
    
        srv.ListenAndServeTLS("cert.pem", "key.pem")
    }
    
    func redirectToHTTPS(tlsPort string) {
        httpSrv := http.Server{
            Addr: httpAddr,
            Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
                host, _, _ := net.SplitHostPort(r.Host)
                u := r.URL
                u.Host = net.JoinHostPort(host, tlsPort)
                u.Scheme="https"
                log.Println(u.String())
                http.Redirect(w,r,u.String(), http.StatusMovedPermanently)
            }),
        }
        log.Println(httpSrv.ListenAndServe())
    }
    

    如果您使用标准端口 (80,443),则不需要拆分连接地址,只需在 URL 上设置方案即可。

    【讨论】:

    • +10。 net.JoinHostPort() 正是我所需要的。
    【解决方案3】:
    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func redirectToHttps(w http.ResponseWriter, r *http.Request) {
        // Redirect the incoming HTTP request. Note that "127.0.0.1:443" will only work if you are accessing the server from your local machine.
        http.Redirect(w, r, "https://127.0.0.1:443"+r.RequestURI, http.StatusMovedPermanently)
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hi there!")
        fmt.Println(r.RequestURI)
    }
    
    func main() {
        http.HandleFunc("/", handler)
        // Start the HTTPS server in a goroutine
        go http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
        // Start the HTTP server and redirect all incoming connections to HTTPS
        http.ListenAndServe(":8080", http.HandlerFunc(redirectToHttps))
    }
    

    【讨论】:

    • 感谢您的帮助!我对几个小时前的另一篇帖子给出了答案。祝你有美好的一天!
    • 明确的 127.0.0.1 地址有问题吗?它可能需要包含域名,例如 "https://" + domain + r.RequestURI。
    • 另外,443 是 https 的默认端口,可以省略。
    【解决方案4】:

    如果您使用自己的多路复用器,这里还有另一个很好的示例和讨论: https://gist.github.com/d-schmidt/587ceec34ce1334a5e60

    【讨论】:

      猜你喜欢
      • 2020-04-16
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2019-09-10
      • 2017-10-06
      • 2017-11-04
      • 1970-01-01
      • 2018-01-19
      相关资源
      最近更新 更多