美文网首页
https配置、双向验证、go代码实现

https配置、双向验证、go代码实现

作者: 被误认为吃货的程序猿 | 来源:发表于2019-11-14 13:39 被阅读0次

    原理

    参照这里: 双向认证SSL原理,已经说的很详细了

    证书生成

    根证书生成

    openssl genrsa -out ca.key 2048
    #这里可以使用 -subj 不用进行交互 当然还可以添加更多的信息
    openssl req -x509 -new -nodes -key ca.key -subj "/CN=test" -days 5000 -out ca.crt
    

    服务端证书生成

    openssl genrsa -out server.key 2048
    #这里的/cn可以是必须添加的 是服务端的域名 或者是etc/hosts中的ip别名
    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 client.key 2048
    openssl req -new -key client.key -subj "/CN=client" -out client.csr
    echo extendedKeyUsage=clientAuth > extfile.cnf
    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out client.crt -days 5000 
    

    nginx 配置

    server {
        listen 443 ssl;
        ssl_certificate server.crt;
        ssl_certificate server.key;
        ssl_client_certificate ca.crt;
        # 开启客户端认证
        ssl_verify_client on;
    }
    

    这里已经可以进行访问,但是由于是自己签发的证书,浏览器会提示不安全。需要在浏览器中添加例外(firefox),或者继续访问(chrome)

    浏览器访问后,出现:no required SSL certificate was sent,说明浏览器已经认证了服务器,但是没有找到证书发送给服务器,因此服务器对客户端没有认证通过,就返回了400错误。这个时候我们需要在浏览器中导入客户端证书,让双向认证完成。

    把客户端证书转为client.p12格式,方便浏览器导入测试

    openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
    

    浏览器导入 client.p12 后,已经能正常访问服务器了。

    客户端代码测试

    用客户端代码测试,能正常访问,go实现,其他的可能需要用到其他格式的证书,但只需要转换一下格式即可:

    package main
    
    import (
        "crypto/tls"
        "crypto/x509"
        "fmt"
        "io/ioutil"
        "net/http"
    )
    
    func main() {
        pool := x509.NewCertPool()
        caCertPath := "certs/cert_server/ca.crt"
    
        caCrt, err := ioutil.ReadFile(caCertPath)
        if err != nil {
            fmt.Println("ReadFile err:", err)
            return
        }
        pool.AppendCertsFromPEM(caCrt)
    
        cliCrt, err := tls.LoadX509KeyPair("certs/cert_server/client.crt", "certs/cert_server/client.key")
        if err != nil {
            fmt.Println("Loadx509keypair err:", err)
            return
        }
    
        tr := &http.Transport{
            TLSClientConfig: &tls.Config{
                RootCAs:      pool,
                Certificates: []tls.Certificate{cliCrt},
                InsecureSkipVerify: true,
            },
        }
        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))
    }
    

    相关文章

      网友评论

          本文标题:https配置、双向验证、go代码实现

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