美文网首页Go
GO自签名证书双向认证

GO自签名证书双向认证

作者: 二三10111 | 来源:发表于2017-09-20 13:54 被阅读0次

    生成SSL证书

    先按照以上操作生成自签名证书。服务端和客户端分别需要引用到的证书如下:

    服务端证书 客户端证书
    ca.crt ca.crt
    server.crt client.crt
    server.key client.key

    服务端

    在go中启动一个https 服务,可以调用http.server 对象
    ListenAndServeTLS(certFile, keyFile string)方法。
    通过注释和实现代码可以知道,该方法的两个参数分别是证书和私钥。也就是server.crtserver.key。并且同时还从http.server对象中获取了一个TLSConfig。TLSConfig 中设置的是根证书ca.crt

    http.server的数据结构:

    http.server

    因此启动一个https server,无其它需求时,简单设置其三个参数即可:

    1. Addr
    2. Handler
    3. TLSConfig
    • Addr 是一个设置服务TCP地址(包括端口号)的字符串。

    • 准备TLSConfig 参数,读取根证书文件。

       pool := x509.NewCertPool()
        caCertPath := "ca.crt"
    
        caCrt, err := ioutil.ReadFile(caCertPath)
        if err != nil {
            fmt.Println("ReadFile err:", err)
            return
        }
        pool.AppendCertsFromPEM(caCrt)
    
    • 准备Handler参数,实现一个带有 http.ResponseWriter和http.Request 的函数,作为处理客户端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")
    }
    
    • 完整代码
    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)
         //初始化一个server 实例。
        s := &http.Server{
            //设置宿主机的ip地址,并且端口号为8081
            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)
        }
    }
    

    客户端

    客户端访问服务端的时候,设置其Transport参数。在构建Transport参数的时候,设置根证书ca.crtclient.crtclient.key

    • 完整代码
    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}
        //这里的ip地址需要在生成自签名证书的时候指定,否则ssl验证不通过。
        resp, err := client.Get("https://127.0.0.1:8081") 
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        fmt.Println(string(body))
    }
    

    Go中的https 双向证书验证便是以上实现。客户端证书只要设置不正确,访问服务端的资源就会失败。https的双向证书验证,是保证数据在客户端和服务端传输时的一种最安全的做法。

    相关文章

      网友评论

        本文标题:GO自签名证书双向认证

        本文链接:https://www.haomeiwen.com/subject/whcosxtx.html