前言

不知為何這半年來開始寫起 Web 前端 (望天),在公司工作真的沒辦法選擇你想要寫什麼語言做什麼東西,只能跟隨組織而動

在開發網站的時候總是會需要做測試,如果希望用手機連到具備安全連線(https)的本地端,就需要自己簽署 Certificate

這邊記錄下如何在 localhost 的情況下也能用 https 連線

注意:裝置連線到本地端需要在同個網域下,不確定 Windows 是否可行

Certificate

Certificate 的機制跟加密有關,基本的概念就是公鑰(Public Key)與私鑰(Private Key)

這邊有一個簡短但解釋得很好的 Youtube 影片

OpenSSL

首先需要用 OpenSSL 來產生 Root Secure Sockets Layer (SSL) 的 Certificate

先產生一把 RSA-2048 key,將他儲存到 rootCA.key 檔案,這時候 opensssl 會要求你輸入一個 pass phrase 密碼,記住這段密碼,在之後生成 Certificate 的時候會用到

1
openssl genrsa -des3 -out rootCA.key 2048

接著用這把 key 來產生 Root SSL certificate,儲存到 rootCA.pem

1
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

在 Mac 上,需要到 Keychain Access 去 import rootCA.pem 然後選擇為信任的簽證

  • System keychains -> File -> Import Items
  • 雙擊匯入的 certificate,在選單中改為 ‘Always Trust’

SSL certificate

建立一個 OpenSSL configuration file server.csr.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=TW
ST=YourState
L=YourLocation
O=YourOrg
OU=YourOrgUnit
emailAddress=YourEmailAddress
CN = localhost

建立一個 v3.ext 檔案,用來產生 X509 v3 certificate

1
2
3
4
5
6
7
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost

這時候使用剛剛已經存好的 server.csr.cnf 來產生 server.key

1
openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server.csr.cnf )

用前面建立好的 root SSL certificate 來產生對應的 server.crt certificate

1
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext

How to use

在 Angular 專案下,可以使用 ng serve 來指定對應的 certificate & key,就能將網站用加密的方式跑在本地端

1
ng server --ssl --ssl-key server.key  --ssl-cert server.crt

要注意的是如果你的 Angular 專案有引入 Service Worker 的話不能用 ng serve 的方式來 run website

另外一個方法適用 Python 的 http.server 函式來達成,但需要寫額外的 script

1
2
3
4
5
6
7
# simple-https-server.py
from http.server import HTTPServer,SimpleHTTPRequestHandler
from socketserver import BaseServer
import ssl
httpd = HTTPServer(('localhost', 8080), SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="server.key", certfile="cert/server.crt", server_side=True)
httpd.serve_forever()

在你的 website location (Angular 會是 dist/) 下執行寫好的 python script,或是讓 python 指定到該位置

要注意的是要用 python 3.0 以上的版本

1
python3 -m simple-https-server.py

ngrok

另外一個更簡便的方式是使用 ngrok 來加密本地端網站

1
./ngrok http http://localhost:8080

執行完以上指令後,他會產生幾組可供連線的加密網址