[Ktor 部署] 添加 https 支持

現(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)便的,最后我的小程序也終于成功上線了!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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