From 29f44c67c808bed9ff1c9d4884d39a1a62d043a7 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 18 Mar 2026 23:13:37 +0800 Subject: [PATCH 01/12] =?UTF-8?q?perf:=20passkey=20=E6=94=AF=E6=8C=81Bitwa?= =?UTF-8?q?rden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/layout/components/user-info/index.vue | 2 +- .../certd-client/src/layout/layout-basic.vue | 5 ++++- .../src/locales/langs/en-US/authentication.ts | 2 ++ .../src/locales/langs/zh-CN/authentication.ts | 2 ++ .../widgets/user-dropdown/user-dropdown.vue | 9 +++++++-- .../src/views/certd/mine/user-profile.vue | 20 +++++++++++++++++-- .../src/views/framework/login/index.vue | 6 ++++++ .../modules/login/service/passkey-service.ts | 2 +- 8 files changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/ui/certd-client/src/layout/components/user-info/index.vue b/packages/ui/certd-client/src/layout/components/user-info/index.vue index ab082f913..0150bb205 100644 --- a/packages/ui/certd-client/src/layout/components/user-info/index.vue +++ b/packages/ui/certd-client/src/layout/components/user-info/index.vue @@ -1,6 +1,6 @@ -
+
@@ -195,70 +185,6 @@ const twoFactor = reactive({ verifyCode: "", }); -const passkeySupported = ref(false); -const passkeyEnabled = ref(false); - -const checkPasskeySupport = () => { - passkeySupported.value = false; - if (typeof window !== "undefined" && "credentials" in navigator && "PublicKeyCredential" in window) { - passkeySupported.value = true; - } -}; - -const handlePasskeyLogin = async () => { - if (!passkeySupported.value) { - notification.error({ message: t("authentication.passkeyNotSupported") }); - return; - } - - loading.value = true; - try { - const optionsResponse: any = await request({ - url: "/passkey/generateAuthentication", - method: "post", - }); - const options = optionsResponse; - - console.log("passkey authentication options:", options, JSON.stringify(options)); - const credential = await (navigator.credentials as any).get({ - publicKey: { - challenge: Uint8Array.from(atob(options.challenge.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0)), - rpId: options.rpId, - allowCredentials: options.allowCredentials || [], - timeout: options.timeout || 60000, - // attestation: options.attestation, - // excludeCredentials: excludeCredentials, - // extensions: options.extensions, - // authenticatorSelection: options.authenticatorSelection, - // hints: options.hints, - // 关键配置在这里 👇 - authenticatorSelection: { - residentKey: "required", // 或 "preferred",请求创建可发现凭证 - requireResidentKey: true, // 为兼容旧浏览器,设置与 residentKey 相同的值 - userVerification: "preferred", // 用户验证策略 - }, - }, - }); - - console.log("passkey authentication credential:", credential, JSON.stringify(credential)); - if (!credential) { - throw new Error("Passkey认证失败"); - } - - const loginRes: any = await UserApi.loginByPasskey({ - credential, - challenge: options.challenge, - }); - - await userStore.onLoginSuccess(loginRes); - } catch (e: any) { - console.error("Passkey登录失败:", e); - notification.error({ message: e.message || "Passkey登录失败" }); - } finally { - loading.value = false; - } -}; - const handleFinish = async () => { loading.value = true; try { @@ -307,9 +233,7 @@ const isOauthOnly = computed(() => { return sysPublicSettings.oauthOnly && settingStore.isPlus && sysPublicSettings.oauthEnabled; }); -onMounted(() => { - checkPasskeySupport(); -}); +onMounted(() => {});