[root@contoso ~]# echo "192.168.10.100 zigoo.com" >> /etc/hosts
[root@contoso ~]# 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
[root@contoso ~]#
[root@contoso ~]# 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
[root@contoso ~]#
[root@contoso ~]# cd $GOPATH/src/contoso.org/client
[root@contoso client]# openssl genrsa -out ca.key 2048 ## 1). 生成一个CA私钥
Generating RSA private key,2048 bit long modulus
.......................................................................................................................................................+++
..........+++
e is 65537 (0x10001)
[root@contoso 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 []:24759362@qq.com
[root@contoso client]#
客户端:
私钥文件 ca.key
数字证书 ca.crt
[root@contoso 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
[root@contoso client]#
[root@contoso client]#cp ca.key ca.crt $GOPATH/src/contoso.org/server
[root@contoso client]#cd $GOPATH/src/contoso.org/server
[root@contoso server]#openssl genrsa -out server.key 2048## 3). 生成一个服务器端私钥
Generating RSA private key,2048 bit long modulus
........+++
......................................+++
e is 65537 (0x10001)
[root@contoso 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,section) []:
Common Name (eg,your name or your server's hostname) []:zigoo.com
Email Address []:24759362@qq.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:
## 5). 使用客户端CA私钥签发服务器端的数字证书
[root@contoso 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/emailAddress=24759362@qq.com
Getting CA Private Key
服务器端:
私钥文件 server.key
数字证书 server.crt
[root@contoso 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
[root@contoso 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)
}
[root@contoso ~]# cd $GOPATH/src/contoso.org/server ##服务器端路径
[root@contoso 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”
[root@contoso ~]#cd $GOPATH/src/contoso.org/server ##服务器端路径
[root@contoso 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))
}
[root@contoso ~]# cd $GOPATH/src/contoso.org/client ##客户端路径
[root@contoso client]# go run client.go ##临时性非全局执行程序,注意,要先启动服务器端
Hi,This is an example of https service in golang!
[{"Name":"jason","Secret":"SRRMb3ZlFFlvdSE="}]
[root@contoso 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 := IoUtil.ReadAll(resp.Body)
fmt.Println(string(body))
}
[root@contoso ~]# cd $GOPATH/src/contoso.org/client ##客户端路径
[root@contoso client]# go run client.go ##临时性非全局执行程序,注意,要先启动服务器端
Hi,"Secret":"SRRMb3ZlFFlvdSE="}]
[root@contoso client]#
我们可以看一下服务器端没有报错,客户端却同样地从服务器端api接口获得了我们需要的数据。