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) { /> + + + + + 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) }