现在的站点不支持 https 都已经说不过去了,特别是最近在搞微信小程序,后端用的 ktor,然而在上架的时候发现,所有的请求都必须是 https 的,那自然就得在 ktor 的程序里把 https 配上了。
首先想办法弄到了一个备过案的域名(不然微信审不过去),绑定解析 IP 后,ssh 登录到远程机器。然后就可以进行一系列操作了,为了方便起见(另外也不想花钱),我选了 Let's Encrypt
的证书服务。
在服务器上先进行安装操作,需要安装 certbot
:
$ sudo apt install whois certbot
安装完成后,就可以申请证书了:
$ export DOMAIN=rarnu.com
$ export [email protected]
$ 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
即是要申请证书的域名,注意必须是域名,IP 地址不可以。后面的 EMAIL 是注册域名时填的邮箱地址(经过实际验证似乎任意邮箱都行,假的也行)。再往后是服务的端口号,默认填80就可以了,如果填了别的,也会被重定向到80,因此在申请证书时,千万记得不能开启 ktor 服务
。最后的 ALIAS 是证书的别名,随便填写就好。
申请成功后,会看到如下的提示:
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
这个时候我们可以进入目录看到证书文件:
$ cd /etc/letsencrypt/live/rarnu.com
$ ls
README cert.pem chain.pem fullchain.pem privkey.pem
下面我们来把证书转换成 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
这个命令会让你设置证书的密码,设置完成后会生成一个 keystore.p12
文件,然后再把 p12 转为我们要的最终文件:
keytool -importkeystore -alias $ALIAS -destkeystore /etc/letsencrypt/live/$DOMAIN/keystore.jks -srcstoretype PKCS12 -srckeystore /etc/letsencrypt/live/$DOMAIN/keystore.p12
这个命令也会让你输入密码,这是 keystore 的密码,可以与 p12 一致或不一致,别忘了就好,完成后生成 keystore.jks
,这个文件就是我们最终要用的了。
现在,打开 ktor 项目,在 application.conf
内加入相关的配置:
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 = [ ... ]
}
}
然后编译并把项目部署到服务器上就可以了,现在可以支持 http 和 https 两种请求方式。
如果希望只启用 https,可以把 port = *
的两行代码删除,这个时候就只能以 https 访问了。
原本到了这里就结束了,但是还有另一种情况,就是本机调试,如果每次改代码都得搞到服务器上去测试,就太累人了,我们有必要在本地也部署一套 https。
操作方式是在 /etc/hosts
里把域名配到本地:
127.0.0.1 rarnu.com
然后直接把服务器端的 keystore.jks
拷到本地的目录(这里指的是 /etc/letsencrypt/live/rarnu.com/
)就可以本地调试了。
原本到了这里又要结束了,但是还有另一种情况,是不采用真实证书,而是用一个假的自签名证书来取代,通常情况下这是没有证书又要调试的最佳办法。
要实现自签名证书非常简单,一段代码即可:
import io.ktor.network.tls.certificates.generateCertificate
import java.io.File
fun main(args: Array) {
generateCertificate(File("keystore.jks"))
}
编译代码前记得先加入依赖:
compile "io.ktor:ktor-network-tls:$ktor_version"
然后就可以把生成的 jks
配到项目里了,需要注意的是自签名证书拥有默认的 alias 和 password:
security {
ssl {
keyStore = keystore.jks
keyAlias = mykey
keyStorePassword = changeit
privateKeyPassword = changeit
}
}
这次是真的结束了,ktor 配 https 还是非常简便的,最后我的小程序也终于成功上线了!