为了账号安全,请及时绑定邮箱和手机立即绑定

响应后验证证书

响应后验证证书

Go
潇潇雨雨 2022-01-17 17:07:38
我想连接到可能不安全的主机,所以我http.Client这样使用:client := &http.Client{    Timeout: timeout,    Transport: &http.Transport{        TLSClientConfig: &tls.Config{            InsecureSkipVerify: true,        },    },}resp, err := client.Get(url)哪个工作得很好,但我似乎找不到事后检查 SSL 证书有效性的方法。我意识到我可以建立两个连接(一个有InsecureSkipVerify一个没有),但我想在不建立另一个连接的情况下做到这一点。
查看完整描述

1 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

可行的。=)


您应该在 Transport 上设置 Dial 和 DialTLS 字段并在那里进行检查。


希望代码是不言自明的,请随时询问。


由于限制,不能在操场上工作!


https://play.golang.org/p/4TkczUEnKn


package main


import (

    "fmt"

    "net/http"

    "net"

    "time"

    "crypto/tls"

)


func DialTLS(network, addr string) (net.Conn, error) {

    conn, err := tls.Dial(network, addr, &tls.Config{

        InsecureSkipVerify: true,

    })


    cs := conn.ConnectionState()

    fmt.Println(cs.Version, cs.HandshakeComplete)

    // insert your check here!


    return conn, err

}


func Dial (network, addr string) (net.Conn, error) {    

    // Copied from DefaultTransport

    dialer := &net.Dialer{

                Timeout:   30 * time.Second,

                KeepAlive: 30 * time.Second,

        }

    conn, err := dialer.Dial(network, addr)


    fmt.Println("unsecure")


    return conn, err

}


func main() {

    client := &http.Client{

        Timeout: time.Second,

        Transport: &http.Transport{

            Dial: Dial,


        // If DialTLS is set, the Dial hook is not used for HTTPS

        // requests and the TLSClientConfig and TLSHandshakeTimeout

        // are ignored. The returned net.Conn is assumed to already be

        // past the TLS handshake.


        // TLSClientConfig: &tls.Config{

        //  InsecureSkipVerify: true,

        // },           

            DialTLS: DialTLS,

        },

    }


    // Deep in transport it checks "tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil"

    // https://golang.org/src/net/http/transport.go#L741

    resp, err := client.Get("https://www.google.com")

    fmt.Println(resp, err, "\n\n")


    resp , err = client.Get("http://www.google.com")

    fmt.Println(resp, err)

}

UPD


UPD2:下面的代码是个坏主意=)。回退逻辑混淆了 http.Clienterror = Get https://www.google.com: http: server gave HTTP response to HTTPS client或者我遗漏了一些东西,好吧,现在由你决定 =)


甚至更好(取决于您的逻辑)。


func DialTLSWithFallback(network, addr string) (net.Conn, error) {

    conn, err := tls.Dial(network, addr, &tls.Config{

        InsecureSkipVerify: true,

    })


    if err != nil {

        // obviously, usecure

        // lets try net.Dial

        // and return, so check bellow wont trigger on wrong connection type

        return &(net.Dialer{

                Timeout:   30 * time.Second,

                KeepAlive: 30 * time.Second,

        }).Dial(network, addr)

    }


    cs := conn.ConnectionState()

    fmt.Println(cs.Version, cs.HandshakeComplete)

    // its "secure" connection

    // check is it strong enough here!


    return conn, err

}

你运输缩小到


        Transport: &http.Transport{

            Dial: DialTLSWithFallback,          

            DialTLS: DialTLSWithFallback,

        }


查看完整回答
反对 回复 2022-01-17
  • 1 回答
  • 0 关注
  • 191 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号