Golang學(xué)習(xí)筆記之HTTPS

一:HTTPS介紹

HTTPS (Secure Hypertext Transfer Protocol)安全超文本傳輸協(xié)議,是一個安全通信通道,它基于HTTP開發(fā)用于在客戶計算機和服務(wù)器之間交換信息。它使用安全套接字層(SSL)進行信息交換,簡單來說它是HTTP的安全版,是使用TLS/SSL加密的HTTP協(xié)議。

HTTP和HTTPS的區(qū)別

? HTTPS是加密傳輸協(xié)議,HTTP是名文傳輸協(xié)議
? HTTPS需要用到SSL證書,而HTTP不用
? HTTPS比HTTP更加安全,對搜索引擎更友好,利于SEO
? HTTPS標(biāo)準(zhǔn)端口443,HTTP標(biāo)準(zhǔn)端口80
? HTTPS基于傳輸層,HTTP基于應(yīng)用層
? HTTPS在瀏覽器顯示綠色安全鎖,HTTP沒有顯示

二、HTTPS證書

正式發(fā)布的時候,是需要購買正規(guī)的證書的。測試程序時,如果沒有,我們可以使用openssl來生成私人的證書。

(1)首先我們先生成證書私鑰

openssl genrsa -out server.key 2048

(2)根據(jù)私鑰生成公鑰

openssl rsa -in server.key -out server.key.public

(2)根據(jù)私鑰生成證書

openssl req -new -x509 -key server.key -outserver.crt -days 365
注意以上命令是生成在當(dāng)前文件夾下的

三、Golang實現(xiàn)HTTPS程序

第一個HTTPS程序

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w,
        "Hi, This is an example of https service in golang!")
}
func main1() {
    http.HandleFunc("/", handler)
    //https監(jiān)聽,必須提供證書文件和對應(yīng)的私鑰文件。
    http.ListenAndServeTLS(":8081", "server.crt",
        "server.key", nil)
}

瀏覽器輸入 https://127.0.0.1:8081進行測試即可。
注意瀏覽器會提示此鏈接不安全,繼續(xù)訪問即可,因為這個證書使我們自己生成的,并不被瀏覽器所承認(rèn)。上面兩個文件的路徑可以是絕對路徑也可以相對,這里在同一文件夾下使用的

四、訪問自己的HTTPS服務(wù)端

go實現(xiàn)的Client端默認(rèn)也是要對服務(wù)端傳過來的數(shù)字證書進行校驗的,因為我們的證書并不是知名CA簽發(fā)的。所以我們要跳過驗證,如下

func main() {
    //要管理代理、TLS配置、keep-alive、壓縮和其他設(shè)置,創(chuàng)建一個Transport
    //Client和Transport類型都可以安全的被多個go程同時使用。出于效率考慮,應(yīng)該一次建立、盡量重用。
    tr := &http.Transport{
        //InsecureSkipVerify用來控制客戶端是否證書和服務(wù)器主機名。如果設(shè)置為true,
        //則不會校驗證書以及證書中的主機名和服務(wù)器主機名是否一致。
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    resp, err := client.Get("https://localhost:8081")
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}
五、對服務(wù)端證書進行校驗

多數(shù)時候,我們需要對服務(wù)端的證書進行校驗,而不是像上面那樣忽略這個校驗。

首先我們來建立我們自己的CA,需要生成一個CA私鑰和一個CA的數(shù)字證書:
(1)生成CA私鑰

openssl genrsa -out ca.key 2048

(2)生成CA證書

openssl req -x509 -new -nodes -key ca.key -subj "/CN=tonybai.com" -days 5000 -out ca.crt

接下來,生成server端的私鑰,生成數(shù)字證書請求,并用我們的ca私鑰簽發(fā)server的數(shù)字證書:
(1)生成服務(wù)端私鑰

openssl genrsa -out server.key 2048

(2)生成證書請求文件

openssl req -new -key server.key -subj "/CN=localhost" -out server.csr

(3)根據(jù)CA的私鑰和上面的證書請求文件生成服務(wù)端證書

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
client.go

//客戶端對服務(wù)器校驗
func main() {
    //CertPool代表一個證書集合/證書池。
    //創(chuàng)建一個CertPool
    pool := x509.NewCertPool()
    caCertPath := "/Users/zt/GOProject/src/https/ca.crt"
    //調(diào)用ca.crt文件
    caCrt, err := ioutil.ReadFile(caCertPath)
    if err != nil {
        fmt.Println("ReadFile err:", err)
        return
    }
    //解析證書
    pool.AppendCertsFromPEM(caCrt)
    
    tr := &http.Transport{
        ////把從服務(wù)器傳過來的非葉子證書,添加到中間證書的池中,使用設(shè)置的根證書和中間證書對葉子證書進行驗證。
        TLSClientConfig: &tls.Config{RootCAs: pool},
    }
    client := &http.Client{Transport: tr}
    resp, err := client.Get("https://localhost:8081")
    if err != nil {
        fmt.Println("Get error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

? Key 是私用密鑰openssl,通常是rsa算法
? Csr 是證書請求文件,用于申請證書。在制作csr文件的時,必須使用自己的私鑰來簽署,還可以設(shè)定一個密鑰
? crt是CA認(rèn)證后的證書文,簽署人用自己的key給你簽署的憑證

六、對客戶端證書進行校驗

要對客戶端數(shù)字證書進行校驗,首先客戶端需要先有自己的證書。
我們以上面的例子為基礎(chǔ),生成客戶端的私鑰與證書。

(1)生成client私鑰

openssl genrsa -out client.key 2048

(2)生成client請求文件

openssl req -new -key client.key -subj "/CN=tonybai_cn" -out client.csr

(3)生成client證書

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 5000
client.go

type myhandler struct {
}

func (h *myhandler) ServeHTTP(w http.ResponseWriter,
    r *http.Request) {
    fmt.Fprintf(w,
        "Hi, This is an example of http service in golang!\n")
}
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)
    s := &http.Server{
        Addr:    ":8081",
        Handler: &myhandler{},
        TLSConfig: &tls.Config{
            ClientCAs:  pool,
            ClientAuth: tls.RequireAndVerifyClientCert,
        },
    }
    err = s.ListenAndServeTLS("server.crt", "server.key")
    if err != nil {
        fmt.Println("ListenAndServeTLS err:", err)
    }
}

server.go

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)
    cliCrt, err := tls.LoadX509KeyPair("client.crt", "client.key")
    if err != nil {
        fmt.Println("Loadx509keypair err:", err)
        return
    }
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{
            RootCAs:      pool,
            Certificates: []tls.Certificate{cliCrt},
        },
    }
    client := &http.Client{Transport: tr}
    resp, err := client.Get("https://localhost: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要使客戶端與服務(wù)器端的通信過程得到安全保證,必須使用的對稱加密算法,但是協(xié)商對稱加密算法的過程,需要使用非對稱加密算法來保證安全,然而直接使用非對稱加密的過程本身也不安全,會有中間人篡改公鑰的可能性,所以客戶端與服務(wù)器不直接使用公鑰,而是使用數(shù)字證書簽發(fā)機構(gòu)頒發(fā)的證書來保證非對稱加密過程本身的安全。這樣通過這些機制協(xié)商出一個對稱加密算法,就此雙方使用該算法進行加密解密。從而解決了客戶端與服務(wù)器端之間的通信安全問題。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于https背景知識密碼學(xué)的一些基本知識 大致上分為兩類,基于key的加密算法與不基于key的加密算法?,F(xiàn)在的算...
    黑手黨老k閱讀 4,159評論 0 2
  • 1.明確https域名,如:tomcat.loc,生成證書時使用 2.創(chuàng)建證書目錄 //進入tmp目錄 cd /h...
    _伽藍(lán)寺聽雨聲閱讀 2,282評論 0 6
  • 001 下班回來后,取了個快遞,然后下樓剪了個頭發(fā)。上次剪頭發(fā)就是在那家店,挺好看,今天繼續(xù)在這家店剪。不過,今天...
    文小輝cool閱讀 234評論 3 1
  • 很久沒給你寫過信了吧,沒想到,在21世紀(jì)的今天,我卻還是喜歡寫信的方式。 今天是端午節(jié),如果沒記錯的話,明天是你的...
    箬茶閱讀 1,185評論 11 7

友情鏈接更多精彩內(nèi)容