1. 程式人生 > >golang https server(二)

golang https server(二)

之前的blog介紹了https的單向認證流程,這裡再介紹一下雙向認證的過程。人多人沒有理解雙向認證的過程,這裡先介紹一下認證流程
這裡寫圖片描述
這裡的ca證書其實是可以不一樣的,這是很多人的誤區,服務端證書用服務端的ca簽名過後,客戶端應該用服務的ca去認證,而不是客戶端自己的ca,如果ca是相同的當然無所謂,下面是生成證書的過程

  • 服務端:
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=ca.com" -days 5000 -out ca.crt

openssl genrsa -out
server.key 2048 openssl req -new -key server.key -subj "/CN=server" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
  • 客戶端:
openssl genrsa -out clinet-ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=ca.com" -days 5000 -out client-ca
.crt openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/CN=client" -out client.csr openssl x509 -req -in client.csr -CA client-ca.crt -CAkey client-ca.key -CAcreateserial -out client.crt -days 5000

這樣證書就生成了,下面看golang的測試程式碼:
服務端:

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 := "client-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) } }

注意,這個裡面使用的是客戶端的ca證書
同理客戶端:

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://server:8081")
    if err != nil {
        fmt.Println("Get error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

使用的是服務的ca這樣就完成了雙向認證的過程