Golang 客户端对服务器端的证书进行校验(单向证书校验)
[[email protected] ~]# echo "192.168.10.100 zigoo.com" >> /etc/hosts
[[email protected] ~]# more /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.100 zigoo.com
[[email protected] ~]#
[[email protected] ~]# tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org├── client
│ ├── client.go
│ └── debug
└── server
├── debug
└── server.go
2 directories, 4 files
[[email protected] ~]#
[[email protected] ~]# cd $GOPATH/src/contoso.org/client
[[email protected] client]# openssl genrsa -out ca.key 2048 ## 1). 生成一个CA私钥
Generating RSA private key, 2048 bit long modulus
.......................................................................................................................................................+++
..........+++
e is 65537 (0x10001)
[[email protected] client]# openssl req -x509 -new -nodes -key ca.key -days 365 -out ca.crt ## 2).使用ca私钥生成客户端的数字证书
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg, city) [Default City]:ShenZhen
Organization Name (eg, company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg, section) []: ## 直接按回车键跳过
Common Name (eg, your name or your server's hostname) []:zigoo.com
Email Address []:[email protected]
[[email protected] client]#
客户端:
私钥文件 ca.key
数字证书 ca.crt
[[email protected] client]#tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org
├── client
│ ├── ca.crt
│ ├── ca.key
│ ├── client.go
│ └── debug
└── server
├── debug
└── server.go
2 directories, 6 files
[[email protected] client]#
[[email protected] client]#cp ca.key ca.crt $GOPATH/src/contoso.org/server
[[email protected] client]#cd $GOPATH/src/contoso.org/server
[[email protected] server]#openssl genrsa -out server.key 2048 ## 3). 生成一个服务器端私钥
Generating RSA private key, 2048 bit long modulus
........+++
......................................+++
e is 65537 (0x10001)
[[email protected] server]# openssl req -new -key server.key -out server.csr ## 4). 使用服务器端私钥生成数字证书请求
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg, city) [Default City]:ShenZhen
Organization Name (eg, company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:zigoo.com
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
##
5). 使用客户端CA私钥签发服务器端的数字证书
[[email protected] server]#openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
Signature ok
subject=/C=CN/ST=GuangDong/L=ShenZhen/O=ZiGoo/CN=zigoo.com/[email protected]
Getting CA Private Key
服务器端:
私钥文件 server.key
数字证书 server.crt
[[email protected] server]#tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org
├── client
│ ├── ca.crt
│ ├── ca.key
│ ├── client.go
│ └── debug
└── server
├── ca.crt
├── ca.key
├── ca.srl
├── debug
├── server.crt
├── server.csr
├── server.go
└── server.key
2 directories, 12 files
[[email protected] server]#
使用Go创建一个HTTPS Web Server
/root/code/go/src/contoso.org/server/server.go :
package main
import (
"fmt"
"net/http"
)
func handler(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "Hi, This is an example of https service in golang!\n")
fmt.Fprintf(res,
`[{"Name":"jason","Age":35,"Weight":60.3,"Speciality":"computer science","Hobby":["tennis","swimming","reading"],"Score":725.5,"Secret":"SRRMb3ZlFFlvdSE="}]`)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServeTLS(":8081", "server.crt", "server.key", nil)
}
[[email protected] ~]#
cd $GOPATH/src/contoso.org/server ##服务器端路径
[[email protected] server]# go run server.go ##临时性非全局执行程序,注意,要先启动服务器端
在浏览器地址栏输入:https://zigoo.com:8081
页面显示:“Your connection is not secure” 浏览器无法访问HTTPS Web Server
该浏览器跳过单向证书校验的临时办法:
Advanced ---> Add Exception...---> Confirm Security Exception
取消在该浏览器上添加的安全异常,恢复到这个浏览器需要的单向证书校验状态:
Preferences ---> Advanced ---> View Certificates ---> Servers ---> Unknown (Not Stored) zigoo.com:8081 ---> Delete...---> OK
a). 在Servers选项卡内滚动列表到下面,发现与zigoo.com内容相关的行删掉;
b)
在Authorities选项卡内滚动列表到下面,发现与ZiGoo内容相关的行删掉;
注意:必须重新启动HTTPS Web Server,按组合键 Ctrl + C 退出 go run server.go 启动的HTTPS Web Server,
这样刷新浏览器才会再一次地看到“Your connection is not secure”
[[email protected] ~]#cd $GOPATH/src/contoso.org/server ##服务器端路径
[[email protected] server]# go run server.go ##临时性非全局执行程序,注意,要先启动服务器端,再一次启动HTTPS Web Server
使用Go创建一个HTTPS Web Client
/root/code/go/src/contoso.org/client/client.go :
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)
tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: pool},
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://zigoo.com:8081")
if err != nil {
fmt.Println("Get error:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
[[email protected] ~]#
cd $GOPATH/src/contoso.org/client ##客户端路径
[[email protected] client]# go run client.go ##临时性非全局执行程序,注意,要先启动服务器端
Hi, This is an example of https service in golang!
[{"Name":"jason","Age":35,"Weight":60.3,"Speciality":"computer science","Hobby":["tennis","swimming","reading"],"Score":725.5,"Secret":"SRRMb3ZlFFlvdSE="}]
[[email protected] client]#
客户端的另外一种实现,服务器端代码保持不变,让客户端跳过对证书的校验:
/root/code/go/src/contoso.org/client/client.go :
package main
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //InsecureSkipVerify参数值只能在客户端上设置有效
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://zigoo.com:8081")
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
[[email protected] ~]#
cd $GOPATH/src/contoso.org/client ##客户端路径
[[email protected] client]# go run client.go ##临时性非全局执行程序,注意,要先启动服务器端
Hi, This is an example of https service in golang!
[{"Name":"jason","Age":35,"Weight":60.3,"Speciality":"computer science","Hobby":["tennis","swimming","reading"],"Score":725.5,"Secret":"SRRMb3ZlFFlvdSE="}]
[[email protected] client]#
我们可以看一下服务器端没有报错,客户端却同样地从服务器端api接口获得了我们需要的数据。