fix(passkey): 修复安卓端 Credential Manager 异常并增强兼容

更新说明:\n1. 优化 Passkey 注册参数(residentKey/hints),提升安卓设备兼容性。\n2. 前台与后台统一增强 Passkey 错误提示,针对 NotReadableError/小米浏览器给出明确引导。\n3. 同步更新相关前端页面逻辑与构建产物。
This commit is contained in:
2026-02-16 00:17:11 +08:00
parent cb35df5f01
commit 7627885b1b
30 changed files with 137 additions and 69 deletions

View File

@@ -24,7 +24,7 @@ import {
updateEmailNotify,
} from '../api/settings'
import { useUserStore } from '../stores/user'
import { createPasskey, isPasskeyAvailable } from '../utils/passkey'
import { createPasskey, getPasskeyClientErrorMessage, isPasskeyAvailable } from '../utils/passkey'
import { validateStrongPassword } from '../utils/password'
const route = useRoute()
@@ -384,12 +384,9 @@ async function onAddPasskey() {
passkeyRegisterOptionsAt.value = 0
await prefetchPasskeyRegisterOptions()
const data = e?.response?.data
const clientMessage = e?.message ? String(e.message) : ''
const message =
data?.error ||
(e?.name === 'NotAllowedError'
? `Passkey注册未完成浏览器返回${clientMessage || '未提供详细原因'}`
: clientMessage || 'Passkey添加失败')
getPasskeyClientErrorMessage(e, 'Passkey注册')
ElMessage.error(message)
} finally {
passkeyAddLoading.value = false

View File

@@ -110,6 +110,36 @@ export function isPasskeyAvailable() {
return typeof window !== 'undefined' && window.isSecureContext && !!window.PublicKeyCredential && !!navigator.credentials
}
function isMiuiBrowser() {
const ua = String(window?.navigator?.userAgent || '')
return /MiuiBrowser|XiaoMi\/MiuiBrowser/i.test(ua)
}
export function getPasskeyClientErrorMessage(error, actionLabel = 'Passkey操作') {
const name = String(error?.name || '').trim()
const message = String(error?.message || '').trim()
if (name === 'NotAllowedError') {
return `${actionLabel}未完成(可能已取消、超时或设备未响应)`
}
if (name === 'NotReadableError') {
if (/credential manager/i.test(message) && isMiuiBrowser()) {
return '当前小米浏览器与系统凭据管理器兼容性较差,请改用系统 Chrome 或 Edge 后重试。'
}
if (/credential manager/i.test(message)) {
return '系统凭据管理器返回异常,请确认已设置系统锁屏并改用系统 Chrome/Edge 后重试。'
}
return message || `${actionLabel}失败(设备读取异常)`
}
if (name === 'SecurityError') {
return '当前环境安全策略不满足 Passkey 要求,请确认使用 HTTPS 且证书有效。'
}
return message || `${actionLabel}失败`
}
export async function createPasskey(rawOptions) {
const publicKey = toCreationOptions(rawOptions)
const credential = await navigator.credentials.create({ publicKey })