duanou9739 2016-06-09 18:04
浏览 30
已采纳

响应后验证证书

I want to connect to potentially insecure hosts, so I'm using http.Client like so:

client := &http.Client{
    Timeout: timeout,
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{
            InsecureSkipVerify: true,
        },
    },
}
resp, err := client.Get(url)

Which works well and fine, but I can't seem to find a way to check the validity of an SSL certificate after the fact. I realize I can make two connections (one with InsecureSkipVerify and one without), but I'd like to do this without making another connection.

  • 写回答

1条回答 默认 最新

  • donglv7097 2016-06-10 00:30
    关注

    Doable. =)

    You should set Dial and DialTLS fields on Transport and do checks there.

    Hope the code is self explanatory, feel free to ask.

    Does not work on playground due to restrictions!

    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, "
    
    ")
    
        resp , err = client.Get("http://www.google.com")
        fmt.Println(resp, err)
    }
    

    UPD

    UPD2: Code below is bad idea =). Fallback logic confuses http.Client error = Get https://www.google.com: http: server gave HTTP response to HTTPS client or I am missing something, well, its up to you now =)

    Or even better (depends on your logic).

    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
    }
    

    And you transport shrinks to

            Transport: &http.Transport{
                Dial: DialTLSWithFallback,          
                DialTLS: DialTLSWithFallback,
            }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 探针系统研发相关实习报告编写问题
  • ¥15 求帮生成一个lattice diamond的许可证
  • ¥15 大一前端新生求教学解答
  • ¥15 如何制作一个可以查看“网游有序列的装备词条”的软件/插件
  • ¥15 CS2打5E与完美天梯匹配会与服务器断开连接(黑框没标明具体原因)
  • ¥15 利用cst反推材料电磁参数,推出想x,y,z方向的相对介电常数与磁导率
  • ¥15 求帮助!用赛灵思FPGA XC7A35T对一个频率50MHz的数字信号读取高低电平,只用HR bank普通单端io进行采样可以吗
  • ¥15 训练准确率100%,测试准确率只有50%
  • ¥15 grafana创建dashhabord提示no data sources of type Prometheus Alert
  • ¥15 python用arima时间序列法预测不出结果 急