From ead942abb2912bba2780160c28ccbd3748f2bb58 Mon Sep 17 00:00:00 2001
From: Ap_Tx <3045929398@qq.com>
Date: Fri, 2 Oct 2026 21:20:26 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E6=A4=8D=E5=BF=BD=E7=95=A5=20?=
=?UTF-8?q?SSL=20=E8=AF=81=E4=B9=A6=E9=94=99=E8=AF=AF=E9=80=89=E9=A1=B9?=
=?UTF-8?q?=EF=BC=88=E8=AE=BE=E7=BD=AE=E5=BC=80=E5=85=B3=20+=20=E9=87=8D?=
=?UTF-8?q?=E5=BB=BA=20HTTP=20=E5=AE=A2=E6=88=B7=E7=AB=AF=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../settings/ResourceManagementSettings.vue | 18 ++++++++++++
apps/app-frontend/src/helpers/settings.ts | 2 ++
.../app-frontend/src/locales/zh-CN/index.json | 6 ++++
.../app-frontend/src/locales/zh-TW/index.json | 6 ++++
apps/app/src/api/settings.rs | 4 ++-
.../20261002010000_add-ignore-ssl-errors.sql | 1 +
packages/app-lib/src/state/mod.rs | 28 +++++++++++++++++--
packages/app-lib/src/state/settings.rs | 13 ++++++++-
packages/app-lib/src/util/fetch.rs | 6 +++-
9 files changed, 78 insertions(+), 6 deletions(-)
create mode 100644 packages/app-lib/migrations/20261002010000_add-ignore-ssl-errors.sql
diff --git a/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue b/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
index 58cc662..8802c5f 100644
--- a/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/ResourceManagementSettings.vue
@@ -253,6 +253,15 @@ const messages = defineMessages({
defaultMessage:
'When CurseForge does not provide a download address, derive its CDN address and try downloading the file automatically. Disable this to use the manual download workflow.',
},
+ ignoreSslErrors: {
+ id: 'app.settings.resources.ignore-ssl-errors',
+ defaultMessage: 'Ignore SSL certificate errors',
+ },
+ ignoreSslErrorsDescription: {
+ id: 'app.settings.resources.ignore-ssl-errors-description',
+ defaultMessage:
+ 'Skip TLS certificate validation for launcher network requests. Only enable this if you trust your network and understand the security risk.',
+ },
mojangAuthService: {
id: 'app.settings.resources.mojang-auth-service',
defaultMessage: 'Mojang authentication service',
@@ -923,6 +932,15 @@ function validateMinecraftDirectory(value) {
/>
+
+ {{ formatMessage(messages.ignoreSslErrors) }}
+
+ {{ formatMessage(messages.ignoreSslErrorsDescription) }}
+
+
+
+
+
diff --git a/apps/app-frontend/src/helpers/settings.ts b/apps/app-frontend/src/helpers/settings.ts
index e4e8fba..996687f 100644
--- a/apps/app-frontend/src/helpers/settings.ts
+++ b/apps/app-frontend/src/helpers/settings.ts
@@ -151,6 +151,7 @@ export type AppSettings = {
curseforge_source: DownloadSourceMode
bypass_curseforge_download_restrictions: boolean
mojang_auth_source: DownloadSourceMode
+ ignore_ssl_errors: boolean
theme: ColorTheme
accent_color: AccentColorSetting
@@ -241,6 +242,7 @@ function normalizeDownloadSettings(settings: AppSettings & LegacyMirrorSettings)
usesLegacyDefaults || !hasLegacySettings ? 'auto' : legacySource(settings.use_curseforge_mirror)
settings.bypass_curseforge_download_restrictions ??= true
settings.mojang_auth_source ??= 'auto'
+ settings.ignore_ssl_errors ??= false
settings.terracotta_public_nodes ??= ['wss://center.node.1tmc.top']
settings.feature_flags ??= { ...DEFAULT_FEATURE_FLAGS }
for (const [key, value] of Object.entries(DEFAULT_FEATURE_FLAGS)) {
diff --git a/apps/app-frontend/src/locales/zh-CN/index.json b/apps/app-frontend/src/locales/zh-CN/index.json
index 3a0bbc0..3b7a5d0 100644
--- a/apps/app-frontend/src/locales/zh-CN/index.json
+++ b/apps/app-frontend/src/locales/zh-CN/index.json
@@ -7219,6 +7219,12 @@
"app.settings.resources.curseforge-restriction-bypass-description": {
"message": "当 CurseForge 不提供下载地址时,根据文件信息推导其 CDN 地址并尝试自动下载。关闭后将使用手动下载流程。"
},
+ "app.settings.resources.ignore-ssl-errors": {
+ "message": "忽略 SSL 证书错误"
+ },
+ "app.settings.resources.ignore-ssl-errors-description": {
+ "message": "跳过启动器网络请求的 TLS 证书校验。仅当你信任当前网络并了解其安全风险时才启用。"
+ },
"app.settings.resources.database-backups": {
"message": "应用数据库备份"
},
diff --git a/apps/app-frontend/src/locales/zh-TW/index.json b/apps/app-frontend/src/locales/zh-TW/index.json
index 3f870e4..e5c41de 100644
--- a/apps/app-frontend/src/locales/zh-TW/index.json
+++ b/apps/app-frontend/src/locales/zh-TW/index.json
@@ -6827,6 +6827,12 @@
"app.settings.resources.curseforge-restriction-bypass-description": {
"message": "當 CurseForge 不提供下載地址時,根據檔案資訊推導其 CDN 地址並嘗試自動下載。關閉後將使用手動下載流程。"
},
+ "app.settings.resources.ignore-ssl-errors": {
+ "message": "忽略 SSL 憑證錯誤"
+ },
+ "app.settings.resources.ignore-ssl-errors-description": {
+ "message": "跳過啟動器網路請求的 TLS 憑證檢查。僅當你信任目前網路並了解其安全風險時才啟用。"
+ },
"app.settings.resources.database-backups": {
"message": "應用程式資料庫備份"
},
diff --git a/apps/app/src/api/settings.rs b/apps/app/src/api/settings.rs
index e281a54..8a49e6a 100644
--- a/apps/app/src/api/settings.rs
+++ b/apps/app/src/api/settings.rs
@@ -33,7 +33,9 @@ pub async fn settings_set(
app: tauri::AppHandle,
settings: Settings,
) -> Result<()> {
- settings::set(settings).await?;
+ settings::set(settings.clone()).await?;
+ let state = State::get().await?;
+ state.update_http_client_for_settings(&settings).await?;
let _ = app.emit("settings", ());
Ok(())
}
diff --git a/packages/app-lib/migrations/20261002010000_add-ignore-ssl-errors.sql b/packages/app-lib/migrations/20261002010000_add-ignore-ssl-errors.sql
new file mode 100644
index 0000000..3d5bbf0
--- /dev/null
+++ b/packages/app-lib/migrations/20261002010000_add-ignore-ssl-errors.sql
@@ -0,0 +1 @@
+ALTER TABLE settings ADD COLUMN ignore_ssl_errors INTEGER NOT NULL DEFAULT 0;
\ No newline at end of file
diff --git a/packages/app-lib/src/state/mod.rs b/packages/app-lib/src/state/mod.rs
index 93666e8..18c5c70 100644
--- a/packages/app-lib/src/state/mod.rs
+++ b/packages/app-lib/src/state/mod.rs
@@ -608,7 +608,11 @@ impl State {
config: &crate::util::proxy::ProxyConfig,
) -> crate::Result<()> {
let _update = self.configured_http_client_update.lock().await;
- let client = crate::util::fetch::build_configured_client(config)?;
+ let settings = Settings::get(&self.pool).await?;
+ let client = crate::util::fetch::build_configured_client(
+ config,
+ settings.ignore_ssl_errors,
+ )?;
crate::state::proxy_settings::set(&self.pool, config).await?;
*self.configured_http_client.write() = client;
Ok(())
@@ -618,6 +622,21 @@ impl State {
self.configured_http_client.read().clone()
}
+ /// 在设置变更(如忽略 SSL 证书开关)后重建 HTTP 客户端。
+ pub(crate) async fn update_http_client_for_settings(
+ &self,
+ settings: &Settings,
+ ) -> crate::Result<()> {
+ let _update = self.configured_http_client_update.lock().await;
+ let proxy = crate::state::proxy_settings::get(&self.pool).await?;
+ let client = crate::util::fetch::build_configured_client(
+ &proxy,
+ settings.ignore_ssl_errors,
+ )?;
+ *self.configured_http_client.write() = client;
+ Ok(())
+ }
+
pub(crate) fn auto_prefers_mirror(&self) -> bool {
self.auto_prefers_mirror.load(Ordering::Relaxed)
}
@@ -839,7 +858,10 @@ impl State {
let auto_prefers_mirror = settings.auto_prefers_mirror();
let proxy_config = proxy_settings::get(&pool).await?;
let configured_http_client =
- crate::util::fetch::build_configured_client(&proxy_config)?;
+ crate::util::fetch::build_configured_client(
+ &proxy_config,
+ settings.ignore_ssl_errors,
+ )?;
tracing::info!("Initializing directories");
DirectoryInfo::move_launcher_directory(
@@ -955,7 +977,7 @@ pub(crate) async fn test_state(
let file_watcher = instances::watcher::init_watcher().await?;
let proxy_config = proxy_settings::get(&pool).await?;
let configured_http_client =
- crate::util::fetch::build_configured_client(&proxy_config)?;
+ crate::util::fetch::build_configured_client(&proxy_config, false)?;
Ok(Arc::new(State {
directories,
diff --git a/packages/app-lib/src/state/settings.rs b/packages/app-lib/src/state/settings.rs
index f74a618..019ddf2 100644
--- a/packages/app-lib/src/state/settings.rs
+++ b/packages/app-lib/src/state/settings.rs
@@ -116,8 +116,9 @@ pub struct Settings {
pub curseforge_source: DownloadSourceMode,
#[serde(default = "default_true")]
pub bypass_curseforge_download_restrictions: bool,
- #[serde(default)]
pub mojang_auth_source: DownloadSourceMode,
+ #[serde(default)]
+ pub ignore_ssl_errors: bool,
#[serde(default, rename = "use_minecraft_mirror", skip_serializing)]
legacy_use_minecraft_mirror: Option,
#[serde(default, rename = "use_modrinth_mirror", skip_serializing)]
@@ -313,6 +314,11 @@ impl Settings {
)
.fetch_one(exec)
.await?;
+ let ignore_ssl_errors: bool = sqlx::query_scalar(
+ "SELECT ignore_ssl_errors FROM settings WHERE id = 0",
+ )
+ .fetch_one(exec)
+ .await?;
let settings = Self {
max_concurrent_downloads: res.max_concurrent_downloads as usize,
max_concurrent_writes: res.max_concurrent_writes as usize,
@@ -331,6 +337,7 @@ impl Settings {
&res.curseforge_source,
),
bypass_curseforge_download_restrictions,
+ ignore_ssl_errors,
mojang_auth_source: DownloadSourceMode::from_string(
&res.mojang_auth_source,
),
@@ -640,6 +647,10 @@ impl Settings {
.bind(self.bypass_curseforge_download_restrictions)
.execute(exec)
.await?;
+ sqlx::query("UPDATE settings SET ignore_ssl_errors = ? WHERE id = 0")
+ .bind(self.ignore_ssl_errors)
+ .execute(exec)
+ .await?;
sqlx::query("UPDATE settings SET mc_memory_optimize = ? WHERE id = 0")
.bind(self.memory.optimize_before_launch)
.execute(exec)
diff --git a/packages/app-lib/src/util/fetch.rs b/packages/app-lib/src/util/fetch.rs
index 882dd81..c174677 100644
--- a/packages/app-lib/src/util/fetch.rs
+++ b/packages/app-lib/src/util/fetch.rs
@@ -1462,9 +1462,13 @@ pub fn build_proxied_client(
pub(crate) fn build_configured_client(
proxy: &crate::util::proxy::ProxyConfig,
+ ignore_ssl_errors: bool,
) -> crate::Result {
proxy
- .apply(reqwest_client_builder())?
+ .apply(
+ reqwest_client_builder()
+ .danger_accept_invalid_certs(ignore_ssl_errors),
+ )?
.build()
.map_err(Into::into)
}