更新了https功能,将原有的服务从http迁移到了https中

This commit is contained in:
2025-09-30 17:26:56 +08:00
parent 7fa1ae6301
commit 7143064a09
4 changed files with 143 additions and 31 deletions

5
.env
View File

@@ -3,4 +3,7 @@ DATABASE_URL=postgres://milkydata:44n6FdB8CdDAk5rk@154.37.213.24:5432/milkydata
WECHAT_APPID="wx5b00eb90621802f7"
WECHAT_SECRET="494efc513faa310bfba588bda2849bfd"
JWT_SECRET="your_super_secret_key"
RUST_LOG=info
SSL_KEY_PATH=/etc/ssl/private/private.key
SSL_CERT_PATH=/etc/ssl/certs/full_chain.pem
RUST_LOG=info
APP_VERSION="0.1.9"

33
Cargo.lock generated
View File

@@ -51,6 +51,7 @@ dependencies = [
"actix-codec",
"actix-rt",
"actix-service",
"actix-tls",
"actix-utils",
"base64",
"bitflags",
@@ -143,6 +144,25 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "actix-tls"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac453898d866cdbecdbc2334fe1738c747b4eba14a677261f2b768ba05329389"
dependencies = [
"actix-rt",
"actix-service",
"actix-utils",
"futures-core",
"impl-more",
"openssl",
"pin-project-lite",
"tokio",
"tokio-openssl",
"tokio-util",
"tracing",
]
[[package]]
name = "actix-utils"
version = "3.0.1"
@@ -166,6 +186,7 @@ dependencies = [
"actix-rt",
"actix-server",
"actix-service",
"actix-tls",
"actix-utils",
"actix-web-codegen",
"bytes",
@@ -2053,6 +2074,7 @@ dependencies = [
"include_dir",
"jsonwebtoken",
"log",
"openssl",
"reqwest",
"serde",
"serde_json",
@@ -2709,6 +2731,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-openssl"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd"
dependencies = [
"openssl",
"openssl-sys",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.26.2"

View File

@@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
actix-files = "0.6.8"
actix-web = "4.11.0"
actix-web = {version = "4.11.0", features=["openssl"]}
chrono = {version = "0.4.41", features=["serde"]}
dotenvy = "0.15.7"
env_logger = "0.11.8"
@@ -13,6 +13,7 @@ error = "0.1.9"
include_dir = "0.7.4"
jsonwebtoken = "9.3.1"
log = "0.4.28"
openssl = "0.10.73"
reqwest = { version = "0.12.23", features=["json"]}
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.143"

View File

@@ -1,7 +1,10 @@
use std::pin::Pin;
use actix_web::middleware::from_fn;
use actix_web::{App, HttpResponse, HttpServer, Responder, delete, get, post, web};
use include_dir::{Dir, include_dir};
use log::{debug, error, info, warn};
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
use reqwest::Client;
use sqlx::postgres::PgPool;
mod auth;
@@ -18,6 +21,23 @@ use crate::models::{Claims, TokenResponse};
static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");
static TEMPLATES_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");
// 加载TLS证书和私钥
fn create_ssl_acceptor() -> Result<SslAcceptorBuilder, Box<dyn std::error::Error>> {
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
// 从环境变量获取证书和私钥路径
let key_path =
std::env::var("SSL_KEY_PATH").unwrap_or_else(|_| "path/to/private.key".to_string());
let cert_path =
std::env::var("SSL_CERT_PATH").unwrap_or_else(|_| "path/to/certificate.crt".to_string());
builder.set_private_key_file(&key_path, SslFiletype::PEM)?;
builder.set_certificate_chain_file(&cert_path)?;
// 返回构建器而不是构建后的接受器
Ok(builder)
}
#[post("/api/login")]
async fn login(
pool: web::Data<PgPool>,
@@ -610,18 +630,19 @@ async fn main() -> std::io::Result<()> {
eprintln!("警告:加载.env文件失败使用系统环境变量: {}", e);
}
// 2. 打印当前 RUST_LOG 的值(关键:验证配置是否生效)
// 打印当前 RUST_LOG 的值
let rust_log = std::env::var("RUST_LOG").unwrap_or_else(|_| "未设置".to_string());
eprintln!("当前 RUST_LOG 级别:{}", rust_log); // 这行用 eprintln!,不受日志级别影响
eprintln!("当前 RUST_LOG 级别:{}", rust_log);
env_logger::init(); // 添加这一行
env_logger::init();
info!("logger init successful");
// 初始化数据库连接池
let pool = match create_pool().await {
Ok(pool) => pool,
Err(e) => {
eprintln!("Failed to create database pool: {}", e);
eprintln!("Please check your database connection configuration in .env file");
error!("Failed to create database pool: {}", e);
error!("Please check your database connection configuration in .env file");
std::process::exit(1);
}
};
@@ -629,45 +650,99 @@ async fn main() -> std::io::Result<()> {
// 初始化HTTP客户端
let http_client = Client::new();
println!("Attempting to start server...");
// 尝试多个端口
let ports = vec![8080, 3000, 8000, 8888];
let mut server = None;
info!("Attempting to start server...");
for port in ports {
// 尝试多个端口
let ports = vec![443, 8443, 8080, 3000, 8000, 8888];
let mut server: Option<
Pin<Box<dyn std::future::Future<Output = std::io::Result<()>> + Unpin>>,
> = None;
let mut bound_port = 0; // 记录绑定的端口
// 使用&ports创建引用迭代器而不是获取所有权
for port in &ports {
let addr = format!("0.0.0.0:{}", port);
println!("Trying to bind to {}", addr);
info!("Trying to bind to {}", addr);
// 为每个服务器创建克隆的连接池和HTTP客户端
let pool_clone = pool.clone();
let http_client_clone = http_client.clone();
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind(&addr)
{
Ok(s) => {
println!("Successfully bound to {}", addr);
server = Some(s);
break;
}
Err(e) => {
eprintln!("Failed to bind to {}: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
eprintln!(" -> Permission denied. Try running with sudo or use a port > 1024");
// 根据端口选择是否使用SSL
if *port == 443 || *port == 8443 {
// 对于443和8443端口使用HTTPS
// 为每个端口创建新的SSL构建器
let ssl_builder = match create_ssl_acceptor() {
Ok(builder) => builder,
Err(e) => {
eprintln!("Failed to create SSL acceptor: {}", e);
continue;
}
};
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind_openssl(&addr, ssl_builder) // 直接传递构建器
{
Ok(s) => {
info!("Successfully bound to {} with HTTPS", addr);
// 将服务器运行Future转换为正确的类型
let server_future = s.run();
// 使用Box::pin将Pin<Box<Server>>转换为Pin<Box<dyn Future<Output = Result<(), std::io::Error>> + Unpin>>
server = Some(Box::pin(server_future));
bound_port = *port; // 记录绑定的端口
break;
}
Err(e) => {
eprintln!("Failed to bind to {} with HTTPS: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
eprintln!(" -> Permission denied. Try running with sudo or use a port > 1024");
}
continue;
}
}
} else {
// 对于其他端口使用HTTP
match HttpServer::new(move || {
create_server_config(pool_clone.clone(), http_client_clone.clone())
})
.bind(&addr)
{
Ok(s) => {
info!("Successfully bound to {} with HTTP", addr);
// 将服务器运行Future转换为正确的类型
let server_future = s.run();
// 使用Box::pin将Pin<Box<Server>>转换为Pin<Box<dyn Future<Output = Result<(), std::io::Error>> + Unpin>>
server = Some(Box::pin(server_future));
bound_port = *port; // 记录绑定的端口
break;
}
Err(e) => {
error!("Failed to bind to {} with HTTP: {}", addr, e);
if e.kind() == std::io::ErrorKind::PermissionDenied {
error!(
" -> Permission denied. Try running with sudo or use a port > 1024"
);
}
continue;
}
continue;
}
}
}
match server {
Some(s) => {
println!("Server started successfully");
s.run().await
// 使用记录的端口判断是否为HTTPS
if bound_port == 443 || bound_port == 8443 {
info!("Server started successfully with HTTPS");
} else {
info!("Server started successfully with HTTP");
}
s.await
}
None => {
eprintln!("Failed to bind to any port. Please check your system configuration.");
error!("Failed to bind to any port. Please check your system configuration.");
std::process::exit(1);
}
}