Go 为任何客户端创建HTTPS测试服务器
由创建的服务器可以验证从其显式创建的客户端的调用:Go 为任何客户端创建HTTPS测试服务器,go,Go,由创建的服务器可以验证从其显式创建的客户端的调用: ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, client") })) defer ts.Close() client := ts.Client() res, err := client.Get(ts.URL) 在client:=ts.client(
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, client")
}))
defer ts.Close()
client := ts.Client()
res, err := client.Get(ts.URL)
在client:=ts.client()
行中
但是,我有一个生产程序,我想将其设置为使用ts.URL
作为主机。我越来越
x509: certificate signed by unknown authority
当我调用它时会出错
如何将
ts
设置为与普通HTTPS服务器一样向客户端进行身份验证?从Go 1.11开始,由于HTTPS的机制,这根本不可能在\u test.Go
程序中完全实现
但是,您可以执行单个证书签名并生成server.crt
和server.key
文件,然后从本地目录无限期地在\u test.go
程序中引用它们
一次性生成.crt
和.key
这是Daksh Shah的媒体文章中指定的步骤的简化版,将在Mac上运行
在需要server.crt
和server.key
文件的目录中,创建两个配置文件
server.csr.cnf
及
v3.ext
然后在该目录中输入以下命令
openssl genrsa-des3-out rootCA.key 2048
#创建密码短语
openssl-req-x509-new-nodes-key rootCA.key-sha256-days 1024-out rootCA.pem-config server.csr.cnf
#输入密码短语
openssl req-new-sha256-nodes-out server.csr-newkey rsa:2048-keyout server.key-config server.csr.cnf
opensslx509-req-in server.csr-CA rootCA.pem-CAkey rootCA.key-CAcreateserial-out server.crt-days 500-sha256-extfile v3.ext
#输入密码短语
最后,通过运行以下命令使系统信任用于对文件进行签名的证书
openrootca.pem
这将在Keychain Acces应用程序中打开证书,该证书将在证书部分中找到,并命名为localhost
。然后要始终相信它
- 按enter键打开其窗口
- 按空格键向下旋转
- 将“使用此证书时:”更改为“始终信任”
- 关闭窗口并验证您的决定
安全添加可信证书的排列,尽管它将证书添加到密钥链并将其标记为“始终信任”,但我的Go程序不会信任它。只有GUI方法将系统置于我的Go程序信任证书的状态
使用HTTPS在本地运行的任何Go程序现在都将信任使用server.crt
和server.key
运行的服务器
运行服务器
您可以创建使用这些凭据的*httptest.Server
实例
func NewLocalHTTPSTestServer(handler http.handler)(*httptest.Server,错误){
ts:=httptest.NewUnstartedServer(处理程序)
证书,错误:=tls.LoadX509KeyPair(“server.crt”,“server.key”)
如果错误!=零{
返回零,错误
}
ts.TLS=&TLS.Config{Certificates:[]TLS.Certificate{cert}
t.StartTLS()
返回ts,无
}
下面是一个示例用法:
func TestLocalHTTPSserver(t*testing.t){
ts,err:=NewLocalHTTPSTestServer(http.HandlerFunc(func)(w http.ResponseWriter,r*http.Request){
fmt.Fprint(w,“你好,客户”)
}))
assert.Nil(t,err)
延迟ts关闭()
res,err:=http.Get(ts.URL)
assert.Nil(t,err)
问候语,err:=ioutil.ReadAll(res.Body)
res.Body.Close()
assert.Nil(t,err)
assert.Equal(t,“你好,客户机”,字符串(问候语))
}
您需要使用正确的证书,或者创建到HTTPS服务器的不安全连接,有点像这样:@Adonis Yeah,在我们的生产代码中启用unsecureskipverify
的可能性不是一个选项。我如何“使用正确的证书”?这基本上就是我在最初的问题中所要求的。你能澄清一下你的情况吗?从这个问题上看,您似乎在试图使用httptest.NewTLSServer
来为生产中的安全通信提供服务。@Adrian不,我绝对不会在生产中使用它。我试图在测试项目中生产组件的实际调用时模拟外部生产组件。由于它在调用中与之通信的其他生产组件使用HTTPS,因此我需要来自NewTLSServer
的模拟服务器也使用HTTPS。@ChrisRedford我从未尝试为httptest生成我自己的证书(或使用有效的证书)。但是,从理论上讲,您可能能够ts:=NewUnstartedServer
而不是ts:=newtlserver
。然后,您可以调整ts.TLS
,这是一个https://golang.org/pkg/crypto/tls/#Config
(您将加载另一个证书)。然后您可以ts.StartTLS()
(因为它是一个“未启动的服务器”)。噢,别忘了推迟ts.Close()
。正如我所说,我从未尝试过,但它可能会起作用。不幸的是,“钥匙链访问”部分(如中所述,该条目可用于危害系统其他部分的安全性)。您的代码最好使用一个空白证书池,只向其中添加您的测试CA,而不是尝试使用系统证书池。我甚至对生产服务器也这样做(让管理它们的ops人员选择是使用系统池还是传入显式CA证书集)。
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=US
ST=RandomState
L=RandomCity
O=RandomOrganization
OU=RandomOrganizationUnit
emailAddress=hello@example.com
CN = localhost
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1