最简单的https server
制作证书
openssl genrsa -out server.key 2048
openssl req -new -x509 -key server.key -out server.crt -days 365
编写程序
package main
import ( "fmt" "net/http" ) func handler(w http.ResponseWriter,r *http.Request) { fmt.Fprintf(w,"Hi,This is an example of https service in golang!") } func main() { http.HandleFunc("/",handler) http.ListenAndServeTLS(":9090","server.crt","server.key",nil) }
启动服务
go run https.go
演示效果
curl -k https://127.0.0.1:9090
Hi,This is an example of https service in golang!
其中的-k就是忽略证书的意思,不验证服务端
当然代码也可以调用,先按照传套路发送请求
package main
import (
"fmt"
"io/IoUtil"
"net/http"
)
func main() {
resp,err := http.Get("https://tim:9090")
if err != nil {
fmt.Println("error:",err)
return
}
defer resp.Body.Close()
body,err := IoUtil.ReadAll(resp.Body)
fmt.Println(string(body))
}
此时会报错
error: Get https://tim:9090: x509: certificate signed by unknown authority
因为我们自己的证书是未认证的。
那么我们先跳过证书验证的这步。
package main
import (
"crypto/tls"
"fmt"
"io/IoUtil"
"net/http"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},}
client := &http.Client{Transport: tr}
resp,err := client.Get("https://tim:9090")
if err != nil {
fmt.Println("error:",err)
return
}
defer resp.Body.Close()
body,err := IoUtil.ReadAll(resp.Body)
fmt.Println(string(body))
}
上面的tim需要注意,如果设置验证证书的话(TLSClientConfig: &tls.Config{InsecureSkipVerify: false}),
那么需要验证两个东西,一个是上证书用的CN的名称一致。
x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs
另一个是证书是否是权威的签发了,否则就是上面的unknown authority了
如果设置成true,则无所谓了,不校验证书,当然不一致也无所谓了。
校验服务端的客户端
如果你是需要安全的监测服务端,当然也是可以的,那么下面演示如何安全建立连接
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=tim" -days 5000 -out ca.crt
openssl genrsa -out server.key 2048
openssl req -new -key server.key -subj "/CN=tim" -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
服务端不需要任何变化,但客户端需要ca证书,
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/IoUtil"
"net/http"
)
func main() {
pool := x509.NewCertPool()
caCertPath := "/mnt/go/src/test/clinet/ca.crt"
caCrt,err := IoUtil.ReadFile(caCertPath)
if err != nil {
fmt.Println("ReadFile err:",err)
return
}
pool.AppendCertsFromPEM(caCrt)
tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: pool},err := client.Get("https://tim:9090")
if err != nil {
fmt.Println("Get error:",err := IoUtil.ReadAll(resp.Body)
fmt.Println(string(body))
}
运行一下
go run clinet.go
Hi,This is an example of https service in golang!
这样客户端的验证服务端的单向验证就是ok了。