update
This commit is contained in:
@@ -448,7 +448,8 @@ export const generatePasskeyRegistrationOptions = async (req: Request, res: Resp
|
|||||||
export const verifyPasskeyRegistration = async (req: Request, res: Response): Promise<void> => {
|
export const verifyPasskeyRegistration = async (req: Request, res: Response): Promise<void> => {
|
||||||
const userId = req.session.userId;
|
const userId = req.session.userId;
|
||||||
const expectedChallenge = req.session.currentChallenge;
|
const expectedChallenge = req.session.currentChallenge;
|
||||||
const { registrationResponse, name } = req.body; // name 是用户给 Passkey 起的名字 (可选)
|
// 将 name 提取出来,其余部分作为 registrationData 对象
|
||||||
|
const { name, ...registrationData } = req.body;
|
||||||
|
|
||||||
if (!userId || req.session.requiresTwoFactor) {
|
if (!userId || req.session.requiresTwoFactor) {
|
||||||
res.status(401).json({ message: '用户未认证或认证未完成。' });
|
res.status(401).json({ message: '用户未认证或认证未完成。' });
|
||||||
@@ -460,7 +461,8 @@ export const verifyPasskeyRegistration = async (req: Request, res: Response): Pr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!registrationResponse) {
|
// 检查 registrationData 是否存在且不为空对象
|
||||||
|
if (!registrationData || Object.keys(registrationData).length === 0) {
|
||||||
res.status(400).json({ message: '缺少注册响应数据。' });
|
res.status(400).json({ message: '缺少注册响应数据。' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -486,7 +488,7 @@ export const verifyPasskeyRegistration = async (req: Request, res: Response): Pr
|
|||||||
|
|
||||||
const verification = await passkeyService.verifyRegistration(
|
const verification = await passkeyService.verifyRegistration(
|
||||||
userId, // <-- 传递 userId 作为第一个参数
|
userId, // <-- 传递 userId 作为第一个参数
|
||||||
registrationResponse,
|
registrationData as any, // 将收集到的字段作为 registrationResponse 传递,可能需要类型断言
|
||||||
expectedChallenge,
|
expectedChallenge,
|
||||||
hostname,
|
hostname,
|
||||||
origin,
|
origin,
|
||||||
|
|||||||
@@ -125,9 +125,9 @@ export class PasskeyService {
|
|||||||
const counter = registrationInfo.counter; // 直接获取 counter
|
const counter = registrationInfo.counter; // 直接获取 counter
|
||||||
|
|
||||||
// --- 直接使用 registrationInfo 的属性 ---
|
// --- 直接使用 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');
|
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');
|
const publicKeyBase64Url = Buffer.from(registrationInfo.credentialPublicKey).toString('base64url');
|
||||||
|
|
||||||
// 获取 transports 信息
|
// 获取 transports 信息
|
||||||
|
|||||||
@@ -905,15 +905,30 @@ const handleRegisterPasskey = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
console.log('[Passkey Register] 开始获取注册选项...');
|
||||||
const optionsResponse = await apiClient.post('/auth/passkey/register-options'); // 使用 apiClient
|
const optionsResponse = await apiClient.post('/auth/passkey/register-options'); // 使用 apiClient
|
||||||
const options = optionsResponse.data;
|
const options = optionsResponse.data;
|
||||||
|
console.log('[Passkey Register] 获取到的注册选项:', JSON.stringify(options, null, 2)); // 记录选项
|
||||||
|
|
||||||
|
console.log('[Passkey Register] 调用 startRegistration...');
|
||||||
let registrationResponse = await startRegistration(options);
|
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');
|
passkeyMessage.value = t('settings.passkey.success.registered');
|
||||||
passkeyName.value = '';
|
passkeyName.value = '';
|
||||||
await authStore.fetchPasskeys(); // 注册成功后刷新列表
|
await authStore.fetchPasskeys(); // 注册成功后刷新列表
|
||||||
} catch (error: any) {
|
} 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') {
|
if (error.name === 'NotAllowedError') {
|
||||||
passkeyError.value = t('settings.passkey.error.cancelled');
|
passkeyError.value = t('settings.passkey.error.cancelled');
|
||||||
} else if (isAxiosError(error) && error.response) { // 使用导入的 isAxiosError
|
} else if (isAxiosError(error) && error.response) { // 使用导入的 isAxiosError
|
||||||
|
|||||||
Reference in New Issue
Block a user