说我想以编程方式获取https://golang.org
。目前golang.org(ssl)有一个错误的证书,颁发给*.appspot.com
所以当我运行时:
package main
import (
"log"
"net/http"
)
func main() {
_, err := http.Get("https://golang.org/")
if err != nil {
log.Fatal(err)
}
}
我得到(正如我所料)
Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org
现在,我想自己信任这个证书(想象一下我可以验证指纹等的自发证书):我如何提出请求并验证/信任证书?
我可能需要使用openssl下载证书,将其加载到我的文件中并填充tls.Config
struct!?
答案 0 :(得分:216)
安全说明:禁用安全检查很危险,应该避免
您可以针对默认客户端的所有请求全局禁用安全检查:
package main
import (
"fmt"
"net/http"
"crypto/tls"
)
func main() {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
_, err := http.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}
您可以禁用客户端的安全检查:
package main
import (
"fmt"
"net/http"
"crypto/tls"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
_, err := client.Get("https://golang.org/")
if err != nil {
fmt.Println(err)
}
}
答案 1 :(得分:12)
这是一种方法,可以在不丢失DefaultTransport
的默认设置的情况下执行此操作,并且不需要根据用户评论提供虚假请求。
defaultTransport := http.DefaultTransport.(*http.Transport)
// Create new Transport that ignores self-signed SSL
httpClientWithSelfSignedTLS := &http.Transport{
Proxy: defaultTransport.Proxy,
DialContext: defaultTransport.DialContext,
MaxIdleConns: defaultTransport.MaxIdleConns,
IdleConnTimeout: defaultTransport.IdleConnTimeout,
ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
警告:仅用于测试/开发目的。还有其他事情,请自担风险!
答案 2 :(得分:11)
所有这些答案都是错误的!不要使用InsecureSkipVerify
来处理与主机名不匹配的CN。 Go开发人员不明智地坚持不禁用主机名检查(具有合法用途 - 隧道,nat,共享群集证书等),同时也有类似但实际完全的内容忽略了证书检查。您需要知道证书有效并由您信任的证书签名。但在常见情况下,您知道CN不会与您连接的主机名相匹配。对于那些,请在ServerName
上设置tls.Config
。如果tls.Config.ServerName
== remoteServerCN,则证书检查将成功。这就是你想要的。 InsecureSkipVerify
表示没有身份验证;这对于一个中间人而言已经成熟;打败使用TLS的目的。
InsecureSkipVerify
有一个合法用途:使用它连接到主机并获取其证书,然后立即断开连接。如果您将代码设置为使用InsecureSkipVerify
,则通常是因为您没有正确设置ServerName
(它需要来自env var或其他东西 - 不要关于这个要求的肚子疼......正确地做。)
特别是,如果您使用客户端证书并依赖它们进行身份验证,那么您基本上会有一个不再实际登录的虚假登录。拒绝执行InsecureSkipVerify
的代码,或者您将以艰难的方式了解它的错误!
答案 3 :(得分:10)
现在,要保持默认的传输设置,正确的方法是(从Go 1.13开始):
customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client = &http.Client{Transport: customTransport}
Transport.Clone复制该传输的深层副本。这样,您不必担心随着时间的推移会丢失添加到Transport
结构中的任何新字段。
答案 4 :(得分:7)
如果您想使用http包中的默认设置,因此您不需要创建新的传输和客户端对象,您可以更改为忽略证书验证,如下所示:
tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
答案 5 :(得分:0)