golang實現(xiàn)openssl自簽名雙向認(rèn)證的詳細(xì)步驟
第一步:生成CA、服務(wù)端、客戶端證書
1. 生成CA根證書 生成CA證書私鑰
openssl genrsa -out ca.key 4096
創(chuàng)建ca.conf 文件
[ req ] default_bits = 4096 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = JiangSu localityName = Locality Name (eg, city) localityName_default = NanJing organizationName = Organization Name (eg, company) organizationName_default = Sheld commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 commonName_default = localhost
生成根證書簽發(fā)申請文件(csr文件)
openssl req \ -new \ -sha256 \ -out ca.csr \ -key ca.key \ -config ca.conf
生成自簽發(fā)根證書(crt文件)
openssl x509 \
-req \
-days 3650 \
-in ca.csr \
-signkey ca.key \
-out ca.pem2. 生成服務(wù)端證書
生成服務(wù)端私鑰
openssl genrsa -out server.key 2048
創(chuàng)建 server.conf 文件
[ req ] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = JiangSu localityName = Locality Name (eg, city) localityName_default = NanJing organizationName = Organization Name (eg, company) organizationName_default = Sheld commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 commonName_default = localhost # 此處尤為重要,需要用該服務(wù)名字填寫到客戶端的代碼中 [ req_ext ] subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1
生成服務(wù)端簽發(fā)申請文件(csr文件)
openssl req \ -new \ -sha256 \ -out server.csr \ -key server.key \ -config server.conf
使用CA證書簽署服務(wù)器證書
openssl genrsa -out client.key 2048
3. 生成客戶端證書
生成客戶端私鑰
openssl genrsa -out client.key 2048
創(chuàng)建 client.conf 文件
[ req ] default_bits = 2048 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = JiangSu localityName = Locality Name (eg, city) localityName_default = NanJing organizationName = Organization Name (eg, company) organizationName_default = Sheld commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 commonName_default = localhost
生成客戶端端簽發(fā)申請文件(csr文件)
openssl req \ -new \ -sha256 \ -out client.csr \ -key client.key \ -config client.conf
使用CA證書簽署客戶端器證書
openssl x509 \
-req \
-days 3650 \
-CA ca.pem \
-CAkey ca.key \
-CAcreateserial \
-in client.csr \
-out client.pem第二步:golang 服務(wù)端、客戶端代碼編寫
1. 項目目錄結(jié)構(gòu)

2. 服務(wù)端代碼:server.go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
)
type MyHandler struct {
}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter,
r *http.Request) {
fmt.Fprint(w, "Hello, HTTPS!")
}
func main() {
pool := x509.NewCertPool() // 創(chuàng)建證書池
caCertPath := "./cert/ca.pem"
caCrt, err := os.ReadFile(caCertPath) // 讀取本地CA證書文件
if err != nil {
fmt.Println("ReadFile err:", err)
return
}
pool.AppendCertsFromPEM(caCrt) // 將證書添加到證書池中
s := &http.Server{ // 創(chuàng)建 HTTP服務(wù)器實例,并設(shè)置服務(wù)器的監(jiān)聽地址(本例中是127.0.0.1:8088)、處理器(即上面定義的myhandler結(jié)構(gòu)體)、以及TLS配置。
Addr: "127.0.0.1:8088",
Handler: &MyHandler{},
TLSConfig: &tls.Config{
ClientCAs: pool, // 指定客戶端需要驗證的CA證書池(即上面創(chuàng)建的pool)
ClientAuth: tls.RequireAndVerifyClientCert, // 要求客戶端在發(fā)送請求時必須攜帶證書
},
}
err = s.ListenAndServeTLS("./cert/server.pem", "./cert/server.key")
if err != nil {
fmt.Println("ListenAndServeTLS err:", err)
}
}3. 客戶端代碼:client.go
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net/http"
"os"
)
func main() {
pool := x509.NewCertPool() // 創(chuàng)建 x509.CertPool,用于存儲CA證書
caCertPath := "./cert/ca.pem" // 從文件中讀取CA證書的內(nèi)容
caCrt, err := os.ReadFile(caCertPath)
if err != nil {
fmt.Println("ReadFile err:", err)
return
}
pool.AppendCertsFromPEM(caCrt) // 將CA證書添加到CertPool中
cliCrt, err := tls.LoadX509KeyPair("./cert/client.pem", "./cert/client.key") //加載客戶端證書和私鑰
if err != nil {
fmt.Println("Loadx509keypair err:", err)
return
}
tr := &http.Transport{ // 創(chuàng)建一個http.Transport,并配置TLS相關(guān)信息
TLSClientConfig: &tls.Config{
RootCAs: pool, // 設(shè)置根證書池
Certificates: []tls.Certificate{cliCrt}, // 設(shè)置客戶端證書和私鑰
},
}
client := &http.Client{Transport: tr} // 創(chuàng)建一個http.Client,并設(shè)置Transport為上面創(chuàng)建的Transport對象
resp, err := client.Get("https://127.0.0.1:8088") // 使用創(chuàng)建的Client發(fā)送GET請求
if err != nil {
fmt.Println("Http Get error:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) // 讀取并打印響應(yīng)體的內(nèi)容
fmt.Println(string(body))
}第三步:驗證
1. 運行服務(wù)端
go run ./server/server.go

2. 運行客戶端
運行客戶端
go run ./client/client.go

到此這篇關(guān)于golang實現(xiàn)openssl自簽名雙向認(rèn)證的詳細(xì)步驟的文章就介紹到這了,更多相關(guān)golang雙向認(rèn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言開發(fā)實現(xiàn)查詢IP信息的MCP服務(wù)器
隨著?MCP?的快速普及和廣泛應(yīng)用,MCP?服務(wù)器也層出不窮,本文將詳細(xì)介紹如何在?Go?語言中使用?go-mcp?庫來開發(fā)一個查詢?IP?信息的?MCP?服務(wù)器,有需要的小伙伴可以參考下2025-04-04
go?tool?pprof?參數(shù)?'-base'?和?'-diff_base&
這篇文章主要介紹了go?tool?pprof?參數(shù)?'-base'?和?'-diff_base'之間的區(qū)別,兩個參數(shù)都是用于計算當(dāng)前?profile文件減去基準(zhǔn)profile文件所獲得的差值,用這個差值生成一個新的profile文件,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Golang基于Vault實現(xiàn)敏感信息保護(hù)
Vault?是一個強大的敏感信息管理工具,自帶了多種認(rèn)證引擎和密碼引擎,本文主要探討應(yīng)用程序如何安全地從?Vault?獲取敏感信息,并進(jìn)一步實現(xiàn)自動輪轉(zhuǎn),感興趣的可以了解一下2023-06-06
Golang中的自定義類型之間的轉(zhuǎn)換的實現(xiàn)(type conversion)
這篇文章主要介紹了Golang中的自定義類型之間的轉(zhuǎn)換的實現(xiàn)(type conversion),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
使用Gorm操作Oracle數(shù)據(jù)庫踩坑記錄
gorm是目前用得最多的go語言orm庫,本文主要介紹了使用Gorm操作Oracle數(shù)據(jù)庫踩坑記錄,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

