現(xiàn)在的站點(diǎn)不支持 https 都已經(jīng)說(shuō)不過(guò)去了,特別是最近在搞微信小程序,后端用的 ktor,然而在上架的時(shí)候發(fā)現(xiàn),所有的請(qǐng)求都必須是 https 的,那自然就得在 ktor 的程序里把 https 配上了。
首先想辦法弄到了一個(gè)備過(guò)案的域名(不然微信審不過(guò)去),綁定解析 IP 后,ssh 登錄到遠(yuǎn)程機(jī)器。然后就可以進(jìn)行一系列操作了,為了方便起見(jiàn)(另外也不想花錢),我選了 Let's Encrypt 的證書服務(wù)。
在服務(wù)器上先進(jìn)行安裝操作,需要安裝 certbot:
$ sudo apt install whois certbot
安裝完成后,就可以申請(qǐng)證書了:
$ export DOMAIN=rarnu.com
$ export EMAIL=admin@rarnu.com
$ export PORT=80
$ export ALIAS=rarnu
$ sudo certbot certonly -n -d $DOMAIN --email "$EMAIL" --agree-tos --standalone --preferred-challenges http --http-01-port $PORT
這里的 DOMAIN 即是要申請(qǐng)證書的域名,注意必須是域名,IP 地址不可以。后面的 EMAIL 是注冊(cè)域名時(shí)填的郵箱地址(經(jīng)過(guò)實(shí)際驗(yàn)證似乎任意郵箱都行,假的也行)。再往后是服務(wù)的端口號(hào),默認(rèn)填80就可以了,如果填了別的,也會(huì)被重定向到80,因此在申請(qǐng)證書時(shí),千萬(wàn)記得不能開(kāi)啟 ktor 服務(wù)。最后的 ALIAS 是證書的別名,隨便填寫就好。
申請(qǐng)成功后,會(huì)看到如下的提示:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for rarnu.com
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/rarnu.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/rarnu.com/privkey.pem
Your cert will expire on 2020-08-22. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
這個(gè)時(shí)候我們可以進(jìn)入目錄看到證書文件:
$ cd /etc/letsencrypt/live/rarnu.com
$ ls
README cert.pem chain.pem fullchain.pem privkey.pem
下面我們來(lái)把證書轉(zhuǎn)換成 ktor 所需的 keystore.jks 文件:
openssl pkcs12 -export -out /etc/letsencrypt/live/$DOMAIN/keystore.p12 -inkey /etc/letsencrypt/live/$DOMAIN/privkey.pem -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem -name $ALIAS
這個(gè)命令會(huì)讓你設(shè)置證書的密碼,設(shè)置完成后會(huì)生成一個(gè) keystore.p12 文件,然后再把 p12 轉(zhuǎn)為我們要的最終文件:
keytool -importkeystore -alias $ALIAS -destkeystore /etc/letsencrypt/live/$DOMAIN/keystore.jks -srcstoretype PKCS12 -srckeystore /etc/letsencrypt/live/$DOMAIN/keystore.p12
這個(gè)命令也會(huì)讓你輸入密碼,這是 keystore 的密碼,可以與 p12 一致或不一致,別忘了就好,完成后生成 keystore.jks,這個(gè)文件就是我們最終要用的了。
現(xiàn)在,打開(kāi) ktor 項(xiàng)目,在 application.conf 內(nèi)加入相關(guān)的配置:
ktor {
deployment {
port = 80
port = ${?PORT}
sslPort = 443
sslPort = ${?PORT_SSL}
}
security {
ssl {
keyStore = /etc/letsencrypt/live/rarnu.com/keystore.jks
keyAlias = rarnu
keyStorePassword = 123456
privateKeyPassword = 123456
}
}
application {
modules = [ ... ]
}
}
然后編譯并把項(xiàng)目部署到服務(wù)器上就可以了,現(xiàn)在可以支持 http 和 https 兩種請(qǐng)求方式。
如果希望只啟用 https,可以把 port = * 的兩行代碼刪除,這個(gè)時(shí)候就只能以 https 訪問(wèn)了。
原本到了這里就結(jié)束了,但是還有另一種情況,就是本機(jī)調(diào)試,如果每次改代碼都得搞到服務(wù)器上去測(cè)試,就太累人了,我們有必要在本地也部署一套 https。
操作方式是在 /etc/hosts 里把域名配到本地:
127.0.0.1 rarnu.com
然后直接把服務(wù)器端的 keystore.jks 拷到本地的目錄(這里指的是 /etc/letsencrypt/live/rarnu.com/)就可以本地調(diào)試了。
原本到了這里又要結(jié)束了,但是還有另一種情況,是不采用真實(shí)證書,而是用一個(gè)假的自簽名證書來(lái)取代,通常情況下這是沒(méi)有證書又要調(diào)試的最佳辦法。
要實(shí)現(xiàn)自簽名證書非常簡(jiǎn)單,一段代碼即可:
import io.ktor.network.tls.certificates.generateCertificate
import java.io.File
fun main(args: Array<String>) {
generateCertificate(File("keystore.jks"))
}
編譯代碼前記得先加入依賴:
compile "io.ktor:ktor-network-tls:$ktor_version"
然后就可以把生成的 jks 配到項(xiàng)目里了,需要注意的是自簽名證書擁有默認(rèn)的 alias 和 password:
security {
ssl {
keyStore = keystore.jks
keyAlias = mykey
keyStorePassword = changeit
privateKeyPassword = changeit
}
}
這次是真的結(jié)束了,ktor 配 https 還是非常簡(jiǎn)便的,最后我的小程序也終于成功上線了!