Golang中如何实现客户端的TLS认证
Golang中如何实现客户端的TLS认证 是否有办法使用TLS对浏览器进行身份验证?
我开发的软件提供了一个Web界面,我希望将访问权限仅限于受信任的客户端(浏览器)。所谓"受信任",指的是那些已手动安装了正确"证书"文件的客户端。
换句话说,我想知道是否能够生成特殊的证书+密钥文件(用于http.ListenAndServeTLS函数),同时生成一个额外的"密钥"文件供客户端浏览器导入到证书存储中。这一切都是为了确保只有导入了此"密钥"文件的浏览器才能访问Web界面。
我不关心服务器信任问题——只关心客户端信任。
谢谢——这非常有帮助。
唯一剩下的问题是:如何创建客户端证书?
更多关于Golang中如何实现客户端的TLS认证的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
主要方法是通过命令行工具:https://gist.github.com/mtigas/952344 包含关于生成证书的CLI教程
当我初次看到您的问题时,关于认证的适用性涌现了许多想法困扰着我,于是我深入探究了为何有人会这样做。关于使用证书的原因我找到了一些很好的解答,这里提供一些让服务器要求客户端证书的帮助信息:https://stackoverflow.com/questions/24181081/request-client-certificate-for-authentication
如需了解Go标准库中TLS相关设置的更多详细信息,请参考:https://godoc.org/crypto/tls#Config
感谢您的问题,让我有机会学到了本不会想到要了解的知识。
谢谢!
供参考,为了让代码正常工作,我需要在 “server.TLSConfig.ClientCAs” 中添加 “ca.crt”
func start_ssl_server() {
fi, _ := os.Stat("ca.key")
if fi == nil || fi.Size() < 100 {
println("ca.key not found")
return
}
// try to start SSL server...
dat, err := ioutil.ReadFile("ca.crt")
if err != nil {
println("ca.crt not found")
// no "ca.crt" file - do not start SSL server
return
}
server := &http.Server{
Addr: ":4433",
TLSConfig: &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
},
}
server.TLSConfig.ClientCAs = x509.NewCertPool()
ok := server.TLSConfig.ClientCAs.AppendCertsFromPEM(dat)
if !ok {
println("AppendCertsFromPEM error")
return
}
println("Starting SSL server at port 4433...")
err = server.ListenAndServeTLS("ca.crt", "ca.key")
if err != nil {
println(err.Error())
}
}
在Golang中实现客户端TLS认证(双向TLS认证)是可行的,这要求客户端提供证书来验证其身份。以下是完整的实现方案:
1. 生成证书和密钥文件
首先,需要生成CA证书、服务器证书和客户端证书:
# 生成CA私钥和证书
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=My CA"
# 生成服务器私钥和证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# 生成客户端私钥和证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=My Client"
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
# 将客户端证书和私钥合并为PKCS#12格式(供浏览器导入)
openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -certfile ca.crt
2. Go服务器端实现
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
// 加载CA证书用于验证客户端
caCert, err := ioutil.ReadFile("ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 配置TLS
tlsConfig := &tls.Config{
ClientCAs: caCertPool,
ClientAuth: tls.RequireAndVerifyClientCert,
MinVersion: tls.VersionTLS12,
}
// 创建HTTP服务器
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if len(r.TLS.PeerCertificates) > 0 {
fmt.Fprintf(w, "Hello, authenticated client! Certificate Subject: %s",
r.TLS.PeerCertificates[0].Subject)
} else {
fmt.Fprintf(w, "No client certificate provided")
}
})
server := &http.Server{
Addr: ":8443",
Handler: mux,
TLSConfig: tlsConfig,
}
log.Println("Server starting on :8443")
log.Fatal(server.ListenAndServeTLS("server.crt", "server.key"))
}
3. 客户端配置说明
用户需要将生成的 client.p12 文件导入到浏览器中:
- Chrome/Edge: 设置 → 隐私和安全性 → 安全 → 管理证书 → 导入
- Firefox: 选项 → 隐私与安全 → 证书 → 查看证书 → 您的证书 → 导入
4. 测试验证
启动服务器后,使用导入了客户端证书的浏览器访问 https://localhost:8443。服务器将验证客户端证书的有效性,只有提供有效证书的客户端才能成功访问。
这种实现确保了只有安装了指定客户端证书的浏览器才能访问你的Web界面,实现了基于客户端证书的身份验证机制。

