修复Windows hello部分情况下设置失败的问题

This commit is contained in:
cc
2026-03-22 23:34:48 +08:00
parent 641a3bf2ab
commit 104a04c5de
3 changed files with 51 additions and 55 deletions

1
.gitignore vendored
View File

@@ -70,3 +70,4 @@ resources/wx_send
概述.md 概述.md
pnpm-lock.yaml pnpm-lock.yaml
/pnpm-workspace.yaml /pnpm-workspace.yaml
wechat-research-site

View File

@@ -32,6 +32,7 @@ const tabs: { id: SettingsTab; label: string; icon: React.ElementType }[] = [
const isMac = navigator.userAgent.toLowerCase().includes('mac') const isMac = navigator.userAgent.toLowerCase().includes('mac')
const isLinux = navigator.userAgent.toLowerCase().includes('linux') const isLinux = navigator.userAgent.toLowerCase().includes('linux')
const isWindows = !isMac && !isLinux
const dbDirName = isMac ? '2.0b4.0.9 目录' : 'xwechat_files 目录' const dbDirName = isMac ? '2.0b4.0.9 目录' : 'xwechat_files 目录'
const dbPathPlaceholder = isMac const dbPathPlaceholder = isMac
@@ -193,9 +194,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
// 检查 Hello 可用性 // 检查 Hello 可用性
useEffect(() => { useEffect(() => {
if (window.PublicKeyCredential) { setHelloAvailable(isWindows)
void PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(setHelloAvailable)
}
}, []) }, [])
// 检查 HTTP API 服务状态 // 检查 HTTP API 服务状态
@@ -2039,33 +2038,29 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
showMessage('请输入当前密码以开启 Hello', false) showMessage('请输入当前密码以开启 Hello', false)
return return
} }
if (!isWindows) {
showMessage('当前系统不支持 Windows Hello', false)
return
}
setIsSettingHello(true) setIsSettingHello(true)
try { try {
const challenge = new Uint8Array(32) const verifyResult = await window.electronAPI.auth.hello('请验证您的身份以开启 Windows Hello')
window.crypto.getRandomValues(challenge) if (!verifyResult.success) {
showMessage(verifyResult.error || 'Windows Hello 验证失败', false)
const credential = await navigator.credentials.create({ return
publicKey: {
challenge,
rp: { name: 'WeFlow', id: 'localhost' },
user: { id: new Uint8Array([1]), name: 'user', displayName: 'User' },
pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
authenticatorSelection: { userVerification: 'required' },
timeout: 60000
}
})
if (credential) {
// 存储密码作为 Hello Secret以便 Hello 解锁时能派生密钥
await window.electronAPI.auth.setHelloSecret(helloPassword)
setAuthUseHello(true)
setHelloPassword('')
showMessage('Windows Hello 设置成功', true)
} }
const saveResult = await window.electronAPI.auth.setHelloSecret(helloPassword)
if (!saveResult.success) {
showMessage('Windows Hello 配置保存失败', false)
return
}
setAuthUseHello(true)
setHelloPassword('')
showMessage('Windows Hello 设置成功', true)
} catch (e: any) { } catch (e: any) {
if (e.name !== 'NotAllowedError') { showMessage(`Windows Hello 设置失败: ${e?.message || String(e)}`, false)
showMessage(`Windows Hello 设置失败: ${e.message}`, false)
}
} finally { } finally {
setIsSettingHello(false) setIsSettingHello(false)
} }

View File

@@ -103,9 +103,7 @@ function WelcomePage({ standalone = false }: WelcomePageProps) {
// 检查 Hello 可用性 // 检查 Hello 可用性
useEffect(() => { useEffect(() => {
if (window.PublicKeyCredential) { setHelloAvailable(isWindows)
void PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(setHelloAvailable)
}
}, []) }, [])
async function sha256(message: string) { async function sha256(message: string) {
@@ -117,35 +115,27 @@ function WelcomePage({ standalone = false }: WelcomePageProps) {
} }
const handleSetupHello = async () => { const handleSetupHello = async () => {
if (!isWindows) {
setError('当前系统不支持 Windows Hello')
return
}
if (!authPassword || authPassword !== authConfirmPassword) {
setError('请先设置并确认应用密码,再开启 Windows Hello')
return
}
setIsSettingHello(true) setIsSettingHello(true)
try { try {
// 注册凭证 (WebAuthn) const result = await window.electronAPI.auth.hello('请验证您的身份以开启 Windows Hello')
const challenge = new Uint8Array(32) if (!result.success) {
window.crypto.getRandomValues(challenge) setError(`Windows Hello 设置失败: ${result.error || '验证失败'}`)
return
const credential = await navigator.credentials.create({
publicKey: {
challenge,
rp: { name: 'WeFlow', id: 'localhost' },
user: {
id: new Uint8Array([1]),
name: 'user',
displayName: 'User'
},
pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
authenticatorSelection: { userVerification: 'required' },
timeout: 60000
}
})
if (credential) {
setEnableHello(true)
// 成功提示?
} }
setEnableHello(true)
setError('')
} catch (e: any) { } catch (e: any) {
if (e.name !== 'NotAllowedError') { setError(`Windows Hello 设置失败: ${e?.message || String(e)}`)
setError('Windows Hello 设置失败: ' + e.message)
}
} finally { } finally {
setIsSettingHello(false) setIsSettingHello(false)
} }
@@ -502,7 +492,17 @@ function WelcomePage({ standalone = false }: WelcomePageProps) {
const hash = await sha256(authPassword) const hash = await sha256(authPassword)
await configService.setAuthEnabled(true) await configService.setAuthEnabled(true)
await configService.setAuthPassword(hash) await configService.setAuthPassword(hash)
await configService.setAuthUseHello(enableHello) if (enableHello) {
const helloResult = await window.electronAPI.auth.setHelloSecret(authPassword)
if (!helloResult.success) {
setError('Windows Hello 配置保存失败')
setLoading(false)
return
}
} else {
await window.electronAPI.auth.clearHelloSecret()
await configService.setAuthUseHello(false)
}
} }
await configService.setOnboardingDone(true) await configService.setOnboardingDone(true)