From ea1af3a5402f4c7a5f216ca57bfc5e3e0646bfcf Mon Sep 17 00:00:00 2001 From: Baobhan Sith <80159437+Heavrnl@users.noreply.github.com> Date: Sun, 27 Apr 2025 01:09:36 +0800 Subject: [PATCH] update --- packages/backend/src/auth/auth.controller.ts | 8 +++++--- .../backend/src/services/passkey.service.ts | 4 ++-- packages/frontend/src/views/SettingsView.vue | 19 +++++++++++++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/auth/auth.controller.ts b/packages/backend/src/auth/auth.controller.ts index b9321e6..43d73fc 100644 --- a/packages/backend/src/auth/auth.controller.ts +++ b/packages/backend/src/auth/auth.controller.ts @@ -448,7 +448,8 @@ export const generatePasskeyRegistrationOptions = async (req: Request, res: Resp export const verifyPasskeyRegistration = async (req: Request, res: Response): Promise => { const userId = req.session.userId; const expectedChallenge = req.session.currentChallenge; - const { registrationResponse, name } = req.body; // name 是用户给 Passkey 起的名字 (可选) + // 将 name 提取出来,其余部分作为 registrationData 对象 + const { name, ...registrationData } = req.body; if (!userId || req.session.requiresTwoFactor) { res.status(401).json({ message: '用户未认证或认证未完成。' }); @@ -460,7 +461,8 @@ export const verifyPasskeyRegistration = async (req: Request, res: Response): Pr return; } - if (!registrationResponse) { + // 检查 registrationData 是否存在且不为空对象 + if (!registrationData || Object.keys(registrationData).length === 0) { res.status(400).json({ message: '缺少注册响应数据。' }); return; } @@ -486,7 +488,7 @@ export const verifyPasskeyRegistration = async (req: Request, res: Response): Pr const verification = await passkeyService.verifyRegistration( userId, // <-- 传递 userId 作为第一个参数 - registrationResponse, + registrationData as any, // 将收集到的字段作为 registrationResponse 传递,可能需要类型断言 expectedChallenge, hostname, origin, diff --git a/packages/backend/src/services/passkey.service.ts b/packages/backend/src/services/passkey.service.ts index 55d6c1a..640a4cf 100644 --- a/packages/backend/src/services/passkey.service.ts +++ b/packages/backend/src/services/passkey.service.ts @@ -125,9 +125,9 @@ export class PasskeyService { const counter = registrationInfo.counter; // 直接获取 counter // --- 直接使用 registrationInfo 的属性 --- - console.log('[PasskeyService] BEFORE Buffer.from(credentialID): Type=', typeof registrationInfo.credentialID, 'Value=', registrationInfo.credentialID); // <-- 添加精确日志 + // console.log('[PasskeyService] BEFORE Buffer.from(credentialID): Type=', typeof registrationInfo.credentialID, 'Value=', registrationInfo.credentialID); // <-- 移除日志 const credentialIdBase64Url = Buffer.from(registrationInfo.credentialID).toString('base64url'); - console.log('[PasskeyService] BEFORE Buffer.from(credentialPublicKey): Type=', typeof registrationInfo.credentialPublicKey, 'Value=', registrationInfo.credentialPublicKey); // <-- 添加精确日志 + // console.log('[PasskeyService] BEFORE Buffer.from(credentialPublicKey): Type=', typeof registrationInfo.credentialPublicKey, 'Value=', registrationInfo.credentialPublicKey); // <-- 移除日志 const publicKeyBase64Url = Buffer.from(registrationInfo.credentialPublicKey).toString('base64url'); // 获取 transports 信息 diff --git a/packages/frontend/src/views/SettingsView.vue b/packages/frontend/src/views/SettingsView.vue index e43f274..7087e60 100644 --- a/packages/frontend/src/views/SettingsView.vue +++ b/packages/frontend/src/views/SettingsView.vue @@ -905,15 +905,30 @@ const handleRegisterPasskey = async () => { return; } try { + console.log('[Passkey Register] 开始获取注册选项...'); const optionsResponse = await apiClient.post('/auth/passkey/register-options'); // 使用 apiClient const options = optionsResponse.data; + console.log('[Passkey Register] 获取到的注册选项:', JSON.stringify(options, null, 2)); // 记录选项 + + console.log('[Passkey Register] 调用 startRegistration...'); let registrationResponse = await startRegistration(options); - await apiClient.post('/auth/passkey/verify-registration', { registrationResponse, name: passkeyName.value }); // 使用 apiClient + console.log('[Passkey Register] startRegistration 返回结果:', JSON.stringify(registrationResponse, null, 2)); // 记录响应 + + const verificationPayload = { ...registrationResponse, name: passkeyName.value }; + console.log('[Passkey Register] 调用验证接口,发送数据:', JSON.stringify(verificationPayload, null, 2)); // 记录发送的数据 + + // 将 startRegistration 返回的对象字段展开,与 name 一起作为请求体发送 + await apiClient.post('/auth/passkey/verify-registration', verificationPayload); // 使用 apiClient + console.log('[Passkey Register] 验证接口调用成功。'); + passkeyMessage.value = t('settings.passkey.success.registered'); passkeyName.value = ''; await authStore.fetchPasskeys(); // 注册成功后刷新列表 } catch (error: any) { - console.error('Passkey 注册流程出错:', error); + // 在 catch 块中记录更详细的错误信息 + console.error('[Passkey Register] 注册流程出错:', error); + console.error('[Passkey Register] 错误详情:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2)); // 尝试记录错误对象的更多属性 + if (error.name === 'NotAllowedError') { passkeyError.value = t('settings.passkey.error.cancelled'); } else if (isAxiosError(error) && error.response) { // 使用导入的 isAxiosError