mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
fix(auth): avoid logout on export-only clear and harden db key auto-fetch
This commit is contained in:
@@ -1347,6 +1347,7 @@ function registerIpcHandlers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clearCache) {
|
||||||
try {
|
try {
|
||||||
const wxidConfigsRaw = cfg.get('wxidConfigs') as Record<string, any> | undefined
|
const wxidConfigsRaw = cfg.get('wxidConfigs') as Record<string, any> | undefined
|
||||||
if (wxidConfigsRaw && typeof wxidConfigsRaw === 'object') {
|
if (wxidConfigsRaw && typeof wxidConfigsRaw === 'object') {
|
||||||
@@ -1369,6 +1370,7 @@ function registerIpcHandlers() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
warnings.push(`清理账号配置失败: ${String(error)}`)
|
warnings.push(`清理账号配置失败: ${String(error)}`)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -2172,7 +2174,7 @@ function registerIpcHandlers() {
|
|||||||
|
|
||||||
// 密钥获取
|
// 密钥获取
|
||||||
ipcMain.handle('key:autoGetDbKey', async (event) => {
|
ipcMain.handle('key:autoGetDbKey', async (event) => {
|
||||||
return keyService.autoGetDbKey(60_000, (message, level) => {
|
return keyService.autoGetDbKey(180_000, (message, level) => {
|
||||||
event.sender.send('key:dbKeyStatus', { message, level })
|
event.sender.send('key:dbKeyStatus', { message, level })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -509,6 +509,58 @@ export class KeyService {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isLoginRelatedText(value: string): boolean {
|
||||||
|
const normalized = String(value || '').replace(/\s+/g, '').toLowerCase()
|
||||||
|
if (!normalized) return false
|
||||||
|
const keywords = [
|
||||||
|
'登录',
|
||||||
|
'扫码',
|
||||||
|
'二维码',
|
||||||
|
'请在手机上确认',
|
||||||
|
'手机确认',
|
||||||
|
'切换账号',
|
||||||
|
'wechatlogin',
|
||||||
|
'qrcode',
|
||||||
|
'scan'
|
||||||
|
]
|
||||||
|
return keywords.some((keyword) => normalized.includes(keyword))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async detectWeChatLoginRequired(pid: number): Promise<boolean> {
|
||||||
|
if (!this.ensureUser32()) return false
|
||||||
|
let loginRequired = false
|
||||||
|
|
||||||
|
const enumWindowsCallback = this.koffi.register((hWnd: any, _lParam: any) => {
|
||||||
|
if (!this.IsWindowVisible(hWnd)) return true
|
||||||
|
const title = this.getWindowTitle(hWnd)
|
||||||
|
if (!this.isWeChatWindowTitle(title)) return true
|
||||||
|
|
||||||
|
const pidBuf = Buffer.alloc(4)
|
||||||
|
this.GetWindowThreadProcessId(hWnd, pidBuf)
|
||||||
|
const windowPid = pidBuf.readUInt32LE(0)
|
||||||
|
if (windowPid !== pid) return true
|
||||||
|
|
||||||
|
if (this.isLoginRelatedText(title)) {
|
||||||
|
loginRequired = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const children = this.collectChildWindowInfos(hWnd)
|
||||||
|
for (const child of children) {
|
||||||
|
if (this.isLoginRelatedText(child.title) || this.isLoginRelatedText(child.className)) {
|
||||||
|
loginRequired = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}, this.WNDENUMPROC_PTR)
|
||||||
|
|
||||||
|
this.EnumWindows(enumWindowsCallback, 0)
|
||||||
|
this.koffi.unregister(enumWindowsCallback)
|
||||||
|
|
||||||
|
return loginRequired
|
||||||
|
}
|
||||||
|
|
||||||
private async waitForWeChatWindowComponents(pid: number, timeoutMs = 15000): Promise<boolean> {
|
private async waitForWeChatWindowComponents(pid: number, timeoutMs = 15000): Promise<boolean> {
|
||||||
if (!this.ensureUser32()) return true
|
if (!this.ensureUser32()) return true
|
||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
@@ -605,6 +657,7 @@ export class KeyService {
|
|||||||
|
|
||||||
const keyBuffer = Buffer.alloc(128)
|
const keyBuffer = Buffer.alloc(128)
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
|
let loginRequiredDetected = false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (Date.now() - start < timeoutMs) {
|
while (Date.now() - start < timeoutMs) {
|
||||||
@@ -624,6 +677,9 @@ export class KeyService {
|
|||||||
const level = levelOut[0] ?? 0
|
const level = levelOut[0] ?? 0
|
||||||
if (msg) {
|
if (msg) {
|
||||||
logs.push(msg)
|
logs.push(msg)
|
||||||
|
if (this.isLoginRelatedText(msg)) {
|
||||||
|
loginRequiredDetected = true
|
||||||
|
}
|
||||||
onStatus?.(msg, level)
|
onStatus?.(msg, level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,6 +691,15 @@ export class KeyService {
|
|||||||
} catch { }
|
} catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loginRequired = loginRequiredDetected || await this.detectWeChatLoginRequired(pid)
|
||||||
|
if (loginRequired) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: '微信已启动但尚未完成登录,请先在微信客户端完成登录后再重试自动获取密钥。',
|
||||||
|
logs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { success: false, error: '获取密钥超时', logs }
|
return { success: false, error: '获取密钥超时', logs }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,9 +305,14 @@ function Sidebar() {
|
|||||||
if (result.warning) {
|
if (result.warning) {
|
||||||
detailLines.push('', `注意:${result.warning}`)
|
detailLines.push('', `注意:${result.warning}`)
|
||||||
}
|
}
|
||||||
window.alert(`账号数据清理完成。\n\n${detailLines.join('\n')}\n\n为保障数据安全,WeFlow 已清除该账号本地缓存/导出相关数据。若需再次获取数据,请手动登录微信客户端并重新在 WeFlow 完成配置。`)
|
const followupHint = shouldClearCacheData
|
||||||
|
? '若需再次获取数据,请手动登录微信客户端并重新在 WeFlow 完成配置。'
|
||||||
|
: '你可以继续使用当前登录状态,无需重新登录。'
|
||||||
|
window.alert(`账号数据清理完成。\n\n${detailLines.join('\n')}\n\n为保障数据安全,WeFlow 已清除该账号本地缓存/导出相关数据。${followupHint}`)
|
||||||
resetClearDialogState()
|
resetClearDialogState()
|
||||||
|
if (shouldClearCacheData) {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('清理账号数据失败:', error)
|
console.error('清理账号数据失败:', error)
|
||||||
window.alert('清理失败,请稍后重试。')
|
window.alert('清理失败,请稍后重试。')
|
||||||
|
|||||||
@@ -36,6 +36,18 @@ interface WxidOption {
|
|||||||
modifiedTime: number
|
modifiedTime: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatDbKeyFailureMessage = (error?: string, logs?: string[]): string => {
|
||||||
|
const base = String(error || '自动获取密钥失败').trim()
|
||||||
|
const tailLogs = Array.isArray(logs)
|
||||||
|
? logs
|
||||||
|
.map(item => String(item || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.slice(-6)
|
||||||
|
: []
|
||||||
|
if (tailLogs.length === 0) return base
|
||||||
|
return `${base};最近状态:${tailLogs.join(' | ')}`
|
||||||
|
}
|
||||||
|
|
||||||
function SettingsPage() {
|
function SettingsPage() {
|
||||||
const {
|
const {
|
||||||
isDbConnected,
|
isDbConnected,
|
||||||
@@ -725,7 +737,10 @@ function SettingsPage() {
|
|||||||
setIsManualStartPrompt(true)
|
setIsManualStartPrompt(true)
|
||||||
setDbKeyStatus('需要手动启动微信')
|
setDbKeyStatus('需要手动启动微信')
|
||||||
} else {
|
} else {
|
||||||
showMessage(result.error || '自动获取密钥失败', false)
|
if (result.error?.includes('尚未完成登录')) {
|
||||||
|
setDbKeyStatus('请先在微信完成登录后重试')
|
||||||
|
}
|
||||||
|
showMessage(formatDbKeyFailureMessage(result.error, result.logs), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -23,6 +23,18 @@ interface WelcomePageProps {
|
|||||||
standalone?: boolean
|
standalone?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatDbKeyFailureMessage = (error?: string, logs?: string[]): string => {
|
||||||
|
const base = String(error || '自动获取密钥失败').trim()
|
||||||
|
const tailLogs = Array.isArray(logs)
|
||||||
|
? logs
|
||||||
|
.map(item => String(item || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.slice(-6)
|
||||||
|
: []
|
||||||
|
if (tailLogs.length === 0) return base
|
||||||
|
return `${base};最近状态:${tailLogs.join(' | ')}`
|
||||||
|
}
|
||||||
|
|
||||||
function WelcomePage({ standalone = false }: WelcomePageProps) {
|
function WelcomePage({ standalone = false }: WelcomePageProps) {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { isDbConnected, setDbConnected, setLoading } = useAppStore()
|
const { isDbConnected, setDbConnected, setLoading } = useAppStore()
|
||||||
@@ -292,7 +304,10 @@ function WelcomePage({ standalone = false }: WelcomePageProps) {
|
|||||||
setIsManualStartPrompt(true)
|
setIsManualStartPrompt(true)
|
||||||
setDbKeyStatus('需要手动启动微信')
|
setDbKeyStatus('需要手动启动微信')
|
||||||
} else {
|
} else {
|
||||||
setError(result.error || '自动获取密钥失败')
|
if (result.error?.includes('尚未完成登录')) {
|
||||||
|
setDbKeyStatus('请先在微信完成登录后重试')
|
||||||
|
}
|
||||||
|
setError(formatDbKeyFailureMessage(result.error, result.logs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user