Rust实践:为ActixWeb启用HTTPS及双向认证
为了数据安全,大多数网站都已经启用了HTTPS。各大平台的API接口必须使用HTTPS进行访问。
这篇文章,就简单介绍一下,如何为ActixWeb服务添加HTTPS并开启双向认证。
证书生成
在配置服务之前,需要有证书,商用证书需要向权威的CA机构申请。当然,国内各大云计算厂商都提供了证书申请的服务。这里我们使用openssl自己生成证书。
CA证书的作用是为证书签名,使用自己生成的CA进行签名,浏览器并“不认同”。但是,我们可以将我们的CA安装到浏览器中。
rem 生成CA证书
openssl req -x509 -newkey rsa:4096 -days 36500 -nodes -keyout ca.key -out ca.crt -subj "/C=CN/ST=GZ/L=HP/O=Yangzx/OU=Administrator/CN=Administrator/emailAddress=1245003727@qq.com" -passout pass:Yzx6606
rem 生成服务端证书
rem 设置域名,可以设置多个,用逗号(,)分隔
echo subjectAltName=DNS:*.server.yangzx.com,DNS:*.server.yangzx.org,DNS:localhost,IP:0.0.0.0,IP:127.0.0.1,IP:192.168.2.104 > server-ext.cnf
rem 生成密钥及证书申请文件,生成server.key文件和server.csr文件
openssl req -newkey rsa:4096 -nodes -keyout server.key -out server.csr -subj "/C=CN/ST=GZ/L=HP/O=Yangzx/OU=YangZX/CN=server.yangzx.com/emailAddress=1245003727@qq.com"
rem 使用ca签名,生成server.crt文件
openssl x509 -req -in server.csr -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -extfile server-ext.cnf
rem 生成客户端证书
rem 设置域名,可以设置多个,用逗号(,)分隔
echo subjectAltName=DNS:*.client.yangzx.com,DNS:*.client.yangzx.org,DNS:localhost,IP:0.0.0.0,IP:127.0.0.1,IP:192.168.2.104 > client-ext.cnf
rem 生成密钥及证书申请文件,生成server.key文件和server.csr文件
openssl req -newkey rsa:4096 -nodes -keyout client.key -out client.csr -subj "/C=CN/ST=GZ/L=HP/O=Yangzx/OU=Yangzx/CN=client.yangzx.com/emailAddress=1245003727@qq.com"
rem 使用ca签名,生成client.crt文件
openssl x509 -req -in client.csr -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -extfile client-ext.cnf
执行完以上指令后,将在当前目录下生成ca.key、ca.crt、server.key、server.crt、client.key、client.crt六个文件。
HTTPS证书配置
我们的web框架是ActixWeb,以下是官方的示例代码:
use actix_web::{web, App, HttpRequest, HttpServer, Responder};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
async fn index(_req: HttpRequest) -> impl Responder {
"Hello."
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder.set_private_key_file("server.key", SslFiletype::PEM)
.unwrap();
builder.set_certificate_chain_file("server.crt").unwrap();
HttpServer::new(|| App::new().route("/", web::get().to(index)))
.bind_openssl("127.0.0.1:8080", builder)?
.run()
.await
}
// 依赖
[dependencies]
actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] }
openssl = { version = "0.10", features = ["v110"] }
使用上面的代码和依赖配置,在编译时会出现以下编译错误:
原因是编译器没有找到openssl,要解决这个问题需要配置环境变量“OPENSSL_DIR”。我是在windows下进行开发,使用Win32 OpenSSL:
openssl安装好了之后,需要做一些调整,下面的操作位置在openssl的安装位置:
- 将 lib/VC/x64/MT/libssl_static.lib 和 lib/VC/x64/MT/libcrypto_static.lib 复制到 lib 目录下,
- 将 lib/libssl_static.lib 改为 lib/libssl.lib,
- 将 lib/libcrypto_static.lib 改为 lib/libcrypto.lib
- 最后,将OPENSSL安装目录添加到环境变量:set OPENSSL_DIR=[OpenSSL安装目录]
保证OPENSSL_DIR目录下的lib目录下有libcrypto.lib文件和libssl.lib文件。当然,也可以使用动态库的lib,但这样生成的exe文件会依赖libcrypto-3-x64.dll和libssl-3-x64.dll。
配置好OPENSSL_DIR环境变量,重新打开一个命令行,再进行编译,就可以编译成功。最终,通过浏览器访问,出现如下界面:
我们可以将我们自己生成的ca.crt安装到“受信任的根证书颁发机构”。安装ca.crt很简单,只需要双击证书文件,根据安装向导进行安装就行,以下是关键的一步:
证书安装完成之后,我们再次访问,问题依旧存在。除了在浏览器上配置ca,还需要在服务端配置ca:
我们可以把ca.crt添加到浏览器中,这样,终于可以正常使用https在浏览器端访问服务了。
配置双向认证
以上的配置,只实现了单向认证:客户端(浏览器)识别正在访问的服务是否合法。有的时候,我们会需要在服务端识别客户端(浏览器)是否合法,这就需要双向认证来实现。
在ActixWeb中配置双向认证非常简单,只需要添加一个条配置即可:
使用浏览器再次访问,会被要求选择证书:
图片中的证书是与我们生成的证书不匹配,如果选择该证书,会出现以下提示:
这个时候,就用到我们的客户端证书。对于客户端证书,除了crt文件之外,还需要私钥。因此需要将两个文件打包一下,下面指令可以将 client.crt和client.key打包成pkcs12格式的证书:
openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt
双击 client.p12,进入安装向导,一路点再一步就可以。客户端证书安装完成后,在浏览器重新访问。应该可以正常访问了。
结语
在今天的网络战场上,HTTPS已不再是可选项,而是守护用户信任的数字生命线。作为互联网传输安装的标准的方式,HTTPS是网站的安装访问方式。虽然使用HTTPS会损耗一些性能,但是却保证了网站的安全。
记住:在网络安全领域,最大的风险不是被攻击,而是认为"不会被攻击"。每一次未加密的请求,都是向黑客敞开的门户;每一次安全警报,都是用户信任的流逝。