# HTTP ###### tags: `http` `security` ### 介紹 HTTP 全名是 「超文本傳輸協定(HyperText Transfer Protocol)」,內容規範了客戶端(client)請求與伺服器(server)回應的標準。 但是這個資料傳輸過程當中,資料都是明文,也就是說如果傳遞的過程中有出現駭客攔截資料,那資料就會洩漏甚至並被盜用。 ![](https://i.imgur.com/k05AQXk.png) 因此,為了保護資料傳輸過程當中不會被攔截、竊取,通常會將資料作加密。 ### HTTP Request HTTP Request(請求)由客戶端發起,送到伺服器去,一個請求可能看起來像下面的樣子: ``` POST /login HTTP/1.1 Host: aaronlife.com Accept: application/json Content-Type: application/json Content-Length: 81 { "UserId": "Aaron Ho, "Password": "AE09-C488-9DFE-0321", "Type": 1, } ``` 其結構分成三個部分: ##### 起始行(Start Line) ``` POST https://www.aaronlife.com/login HTTP/1.1 ``` 1. POST:要使用的HTTP請求方法(Method),HTTP方法有下面幾種: | 方法名稱 | 說明 | | ---------- | --------------------------------------- | | **GET** | 取得資料 | | **POST** | 提交資料、更新資料 | | **PUT** | 新增資料 | | **DELETE** | 刪除資料 | | HEAD | 與GET相同,但回應不會有資料本體(Body) | | CONNECT | 讓指定的資源跟伺服器連線 | | OPTIONS | 指定資源的溝通方式 | | TRACE | 指定資源跟伺服器之間的來回測試 | | PATCH | 修改部分資料 | > **補充** > > 粗體字為較常用的四個方法,該四個方法長統稱為CRUD(Create、Read、Update、Delete - 增、刪、讀、改)。 2. `https://www.aaronlife.com/login`:方法後面接的是URL,要發出的請求的對象,通常為伺服器的位址。 3. `HTTP/1.1`該請求使用的HTTP版本。 ##### 表頭(Headers) ``` Host: aaronlife.com Accept: application/json Content-Type: application/json Content-Length: 81 ``` 表頭用來存放跟請求相關的一些設定,例如:請求的資料本體類型、認證資料、請求的資料長度等等;每一筆表頭設定都是以:「欄位名稱」跟「欄位值」的型態來表示,例如:`Content-Type`為欄位名稱,而`application/json`為欄位值。 ##### 資料本體(Body) ``` { "UserId": "Aaron Ho, "Password": "AE09-C488-9DFE-0321", "Type": 1, } ``` 資料本體則是該次請求要發送給對方的資料,可能是JSON、XML、檔案、純文字等等資料。 ### HTTP Response 伺服器端收到請求後會發出HTTP Response(回應),一個HTTP Response看起來像下面的樣子: ``` HTTP/1.1 200 OK Date: Thu, 24 Dec 2021 04:55:38 GMT Content-Type: application/json Content-Length: 19 Connection: keep-alive CF-Cache-Status: DYNAMIC {"status":"ok"} ``` ##### 狀態列(Status Line) ``` HTTP/1.1 200 OK ``` 1. `HTTP/1.1`:伺服器端回應格式使用的HTTP版本。 2. `200`:回應的狀態碼,2xx為成功,3xx為重新導向、4xx為客戶端錯誤、5xx為伺服器錯誤。 > **補充** > > 詳細狀態碼可參考:https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Status 3. `OK`:回應的狀態描述。 ##### 表頭(Headers) ``` Date: Thu, 24 Dec 2021 04:55:38 GMT Content-Type: application/json Content-Length: 19 Connection: keep-alive CF-Cache-Status: DYNAMIC ``` 回應的表頭與請求的表頭格式一樣都是「欄位名稱」與「欄位值」的組合,裡面可能有回應時間、回應資料內容格式等等設定。 ##### 資料本體(Body) ``` {"status":"ok"} ``` 該次回應的內容,與請求一樣,可能是JSON、XML、檔案、純文字等等資料,可以根據表頭的`Content-Type`欄位得知內資料本體是什麼樣的資料格式。 ## 加密 加密指的是把明文(可以讀取的內容)資料轉換成密文(也就是無法讀取的內容),並且密文能藉由特定的解密過程,將無法讀取的內容回復成原來的可以讀取的明文。 > 加密和雜湊不同,雜湊過的內容是無法恢復成原來的樣子的。 ### 共用金鑰加密 又稱為對稱式加密,加密的時候必須透過一個特定的金鑰(也可稱為一組密碼)來加密資料,解密的時候必須使用相同的金鑰來還原資料。這個用來加密及解密的方式,就稱為「共用金鑰加密」或「對稱式加密」。 > AES就是一種對稱式加密的方式。 經過共用金鑰加密,資料本身已經無法被沒有金鑰對象讀取,但是如果用於網路傳輸,加密及解密的雙方都必須要知道該金鑰,所以在傳輸加密後的資料之前,必須雙方先交換金鑰,而這個金鑰未經過加密,還是有被攔截的可能,如果金鑰被攔截了,後面的資料即使經過加密,也都可能被使用金要來做解密了。 因此,如果要有安全的資料傳輸,需要其他加密方式。 ### 公開金鑰加密 又稱為「非對稱式加密」;在這個加密的方式當中,資料傳輸的方會有成對的兩個金鑰:一個稱為「公鑰」,一個稱為「私鑰」,顧名思義,這個公鑰是可以公開給所有人都看得到,而私鑰是則保留在資料提供者自己的手上,不需要提供給解密方;每個資料被任意一個金鑰(公鑰或私鑰)加密後,必須要透過與之配對的另一個金鑰才能解密;例如用私鑰加密的資料,就只能被我的公鑰解密,被公鑰加密的資料,只能使用私鑰來解密。 在這樣的規則下,進行資料傳輸,即使公鑰被攔截了,攔截方也無法解密資料,因為經過公鑰加密的資料必須透過私鑰來解密。 但很可惜的,即使是這樣,網路上的資料傳輸,還是無法非常安全,因為雖然公鑰對方可以看到並用來解密,但因為公鑰無法證明是不是資料提供方所有,所以當駭客在中間攔截了公鑰後,將公鑰換成另一個,那接收方如果使用了駭客的公鑰加密資料來做回應,駭客就可以輕易取得該回應資料了,這個手段又稱為「中間人攻擊」。 因此,我們需要一個能證明公鑰屬於誰的方法。 ### 數位憑證 因此就出現了 「憑證頒發機構」,當資料通訊的雙方要開始進行資料傳輸之前資料提供者必須提供「公鑰」跟「email」,向憑證頒發機構申請憑證,憑證頒發機構核可後,便會透過「數位簽章」來打包資料提供者的資訊,並製作成「數位憑證」。 當通訊開始時,資料提供者會先傳遞數位憑證接收方,接收方便可以透過數位簽章,來證明憑證的內容確實是屬於資料提供者的;這樣,就可以證明公鑰是不是屬於對方的,即使駭客想從中調包公鑰,但因為憑證頒發機構的數位簽章,其通訊過程駭客無法介入,因此就可以證明公鑰的所屬者。 ## HTTPS HTTPS 全名 「超文本傳輸安全協定」,HTTP後面多出來的S是 Secure的意思;HTTPS 透過 HTTP 進行通訊,但傳輸的資料都會使用使用 「SSL/TLS」進行加密,以就是類似於前面介紹的的加密方式,在 HTTP之上定義了較安全的資料傳輸方式。 由於非對稱加密的運算量較高,效率較慢,所以在實際的應用上,會透過公開金鑰加密傳送共用金鑰,再透過共用金鑰加來進行進行之後的資料傳輸工作,這樣就可以兼顧了安全性及資料傳輸效率。 ## 瀏覽器的支援 在Google Chrome瀏覽器列上,如果是經過加密的連線,網址左邊會出現一個鎖頭的圖案,代表是經過憑證加密的連線,也就是https連線。 ![](https://i.imgur.com/EzqjS0u.png) 但如果網址左邊會出現三角形驚嘆號圖案,並出現「不安全」的訊息,則代連線沒有經過加密,也就是http連線。 ![](https://i.imgur.com/Mto929S.png) >如果你今天連線的網頁資料比較敏感,例如銀行刷卡服務、轉帳等等,需注意連線有沒有經過加密,否則就不要繼續操作,避免資料被攔截。