需要安装好 go 1.15 以下的版本
HTTP
直接监听在 8080 端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main
import ( "fmt" "net/http" )
func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi, This is an example of http service in golang!") }
func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
|
HTTPS 忽略服务端证书校验
用 ListenAndServeTLS 来替换掉 ListenAndServe,需要指定服务端的证书和私钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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(":8081", "server.crt", "server.key", nil) }
|
这时候会提示风险,接受风险后正常访问
接下来使用 go 写一个客户端来进行连接
(github 上面下载的证书过期了,重新生成一下
openssl genrsa -out server.key 2048 #生成私钥
openssl req -new -x509 -key server.key -out server.crt -days 365 #生成证书
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main
import ( "fmt" "io/ioutil" "net/http" )
func main() { resp, err := http.Get("https://localhost:8081") if err != nil { fmt.Println("error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
|
请求的时候报了一个错误,意思是客户端认为证书不是由知名的 CA 签发的
修改客户端的代码,略过对证书的校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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://localhost:8081")
if err != nil { fmt.Println("error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
|
HTTPS 对服务端证书进行校验
多数时候需要对服务端证书进行校验,而不是像上面那样忽略这个校验,通过校验我们可以确认:1、服务端传来的证书是由某个特定 CA 签发的(如果是 self-signed,也无妨)2、服务端传来的数字证书没有被中途篡改过
接下来建立一个属于自己的 CA
1 2 3 4 5 6 7 8 9 10
| #生成一个ca私钥 openssl genrsa -out ca.key 2048 #生成一个ca证书 openssl req -x509 -new -nodes -key ca.key -subj "/CN=localhost" -days 5000 -out ca.crt #生成服务端私钥 openssl genrsa -out server.key 2048 #生成服务端证书请求 openssl req -new -key server.key -subj "/CN=localhost" -out server.csr #用我们的ca私钥签发server的数字证书 openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
|
此时先用客户端加载 ca 证书
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "crypto/tls" "crypto/x509" "fmt" "io/ioutil" "net/http" )
func main() { pool := x509.NewCertPool() caCertPath := "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}, } client := &http.Client{Transport: tr} resp, err := client.Get("https://localhost:8081") if err != nil { fmt.Println("Get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
|
HTTPS 双向校验
服务端对客户端的证书进行校验
1 2 3 4 5 6
| #生成客户端私钥 openssl genrsa -out client.key 2048 #生成客户端证书请求 openssl req -new -key client.key -subj "/CN=localhost_cn" -out client.csr #使用ca生成对客户端证书 openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 5000
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package main
import ( "crypto/tls" "crypto/x509" "fmt" "io/ioutil" "net/http" )
type myhandler struct { }
func (h *myhandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi, This is an example of http service in golang!\n") }
func main() { pool := x509.NewCertPool() caCertPath := "ca.crt"
caCrt, err := ioutil.ReadFile(caCertPath) if err != nil { fmt.Println("ReadFile err:", err) return } pool.AppendCertsFromPEM(caCrt)
s := &http.Server{ Addr: ":8081", Handler: &myhandler{}, TLSConfig: &tls.Config{ ClientCAs: pool, ClientAuth: tls.RequireAndVerifyClientCert, }, }
err = s.ListenAndServeTLS("server.crt", "server.key") if err != nil { fmt.Println("ListenAndServeTLS err:", err) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package main
import (
"crypto/tls" "crypto/x509" "fmt" "io/ioutil" "net/http" )
func main() { pool := x509.NewCertPool() caCertPath := "ca.crt"
caCrt, err := ioutil.ReadFile(caCertPath) if err != nil { fmt.Println("ReadFile err:", err) return } pool.AppendCertsFromPEM(caCrt)
cliCrt, err := tls.LoadX509KeyPair("client.crt", "client.key") if err != nil { fmt.Println("Loadx509keypair err:", err) return }
tr := &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: pool, Certificates: []tls.Certificate{cliCrt}, }, } client := &http.Client{Transport: tr} resp, err := client.Get("https://localhost:8081") if err != nil { fmt.Println("Get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
|
通是通了,但是抓包看不到区别
参考:
最后更新时间: