Files
qwen-code/packages/vscode-ide-companion/docs-tmp/AUTH_FLOW.md
yiliang114 732220e651 wip(vscode-ide-companion): 实现 quick win 功能
- 将 WebView 调整到编辑器右侧
- 添加 ChatHeader 组件,实现会话下拉菜单
- 替换模态框为紧凑型下拉菜单
- 更新会话切换逻辑,显示当前标题
- 清理旧的会话选择器样式
基于 Claude Code v2.0.43 UI 分析实现。
2025-11-19 00:16:45 +08:00

9.4 KiB
Raw Blame History

Qwen Code 认证流程说明

🔐 认证流程概览

用户打开 Chat UI
  ↓
WebViewProvider.show()
  ↓
检查 agentInitialized 标志
  ├─ 如果为 true → 跳过初始化(使用现有连接)
  └─ 如果为 false → 继续初始化
      ↓
      authStateManager.hasValidAuth()
      ├─ 有效缓存 → needsAuth = false
      └─ 无缓存/过期 → needsAuth = true
      ↓
      尝试恢复本地 session
      ├─ 成功 → sessionRestored = true, needsAuth = false
      └─ 失败 → 继续
      ↓
      如果 !sessionRestored && needsAuth
        ↓
        authenticate() (仅一次!) ✅
        ↓
        newSession()
        ↓
        saveAuthState()
      ↓
      agentInitialized = true

已修复的问题

问题 1: 嵌套 try-catch 导致重复认证(已修复)

之前的代码

try {
  if (switchSession fails) {
    authenticate(); // 第 1 次
  } else {
    authenticate(); // 第 1 次
  }
} catch {
  authenticate(); // 第 2 次!❌
}

修复后的代码

let needsAuth = true;
let sessionRestored = false;

// 检查缓存
if (hasValidAuth) {
  needsAuth = false;
}

// 尝试恢复 session
try {
  if (switchSession succeeds) {
    sessionRestored = true;
    needsAuth = false;
  }
} catch {
  // 只记录日志,不触发认证
}

// 只在必要时认证(最多一次)
if (!sessionRestored && needsAuth) {
  authenticate(); // 只会执行一次!✅
  newSession();
}

问题 2: agentInitialized 标志未重置(已修复)

问题描述 清除认证缓存后,agentInitialized 标志仍为 true,导致不会重新初始化。

修复方案

// WebViewProvider.ts
resetAgentState(): void {
  this.agentInitialized = false;
  this.agentManager.disconnect();
}

// extension.ts
vscode.commands.registerCommand('qwenCode.clearAuthCache', async () => {
  await authStateManager.clearAuthState();
  webViewProvider.resetAgentState(); // ✅ 重置状态
});

🎯 正确的使用方式

场景 1: 正常使用(无需手动操作)

第1次打开 Chat UI:
  → 没有缓存
  → 需要登录 (1 次)
  → 保存缓存 (24小时)

第2次打开 Chat UI (24小时内):
  → 有缓存
  → 不需要登录 ✅

第3次打开 Chat UI (24小时后):
  → 缓存过期
  → 需要登录 (1 次)
  → 更新缓存

场景 2: 手动清除缓存

1. 执行命令: Qwen Code: Clear Authentication Cache
   → 清除缓存
   → 重置 agentInitialized 标志
   → 断开现有连接

2. 下次打开 Chat UI:
   → 没有缓存
   → 需要登录 (1 次) ✅
   → 保存新缓存

场景 3: 缓存有效但 token 失效

打开 Chat UI:
  → 缓存有效,跳过认证
  → 尝试创建 session
  → Session 创建失败token 已过期)
  ↓
  【自动恢复】✅
  → 清除缓存
  → 重新认证 (1 次)
  → 保存新缓存
  → 重新创建 session

⚠️ 可能导致多次登录的情况

情况 1: Session 恢复失败 + 认证重试

如果 session 恢复失败,且认证也失败,会触发重试(最多 3 次):

尝试恢复 session → 失败
  ↓
认证尝试 #1 → 失败
  ↓ (等待 1 秒)
认证尝试 #2 → 失败
  ↓ (等待 2 秒)
认证尝试 #3 → 失败
  ↓
抛出错误

这是正常的重试机制,用于处理网络临时故障。

情况 2: 多次打开/关闭 Chat UI

如果频繁打开关闭 Chat UI

打开 #1 → 登录 → agentInitialized = true
关闭
打开 #2 → 使用现有连接 ✅ (不需要登录)
关闭
打开 #3 → 使用现有连接 ✅ (不需要登录)

这是正常行为,不会重复登录。

🐛 如何诊断"两次登录"问题

1. 查看详细日志

打开 VSCode 输出面板:

View → Output → 选择 "Qwen Code Companion"

查找以下关键日志:

正常流程(只登录一次):

[WebViewProvider] Starting initialization, workingDir: /path/to/workspace
[QwenAgentManager] Using cached authentication  ← 或者跳过这行(首次登录)
[QwenAgentManager] Creating new session...
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T...  ← 只出现一次!
[QwenAgentManager] Call stack: ...
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...
[QwenAgentManager] ✅ Authentication successful on attempt 1
[QwenAgentManager] New session created successfully
[AuthStateManager] Auth state saved

异常流程(登录多次):

[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T10:00:00  ← 第 1 次
[QwenAgentManager] Call stack: ...
[QwenAgentManager] ✅ Authentication successful on attempt 1
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at 2025-11-17T10:00:05  ← 第 2 次!❌
[QwenAgentManager] Call stack: ...

如果看到两个 "AUTHENTICATION CALL STARTED",说明 authenticateWithRetry() 被调用了两次!

2. 分析调用栈

查看每次认证调用的堆栈信息:

[QwenAgentManager] Call stack:
    at QwenAgentManager.authenticateWithRetry (/path/to/QwenAgentManager.ts:206)
    at QwenAgentManager.connect (/path/to/QwenAgentManager.ts:162)  ← 正常调用
    at WebViewProvider.show (/path/to/WebViewProvider.ts:131)

或者:

[QwenAgentManager] Call stack:
    at QwenAgentManager.authenticateWithRetry (/path/to/QwenAgentManager.ts:206)
    at QwenAgentManager.connect (/path/to/QwenAgentManager.ts:184)  ← 缓存失效重试!
    at WebViewProvider.show (/path/to/WebViewProvider.ts:131)

3. 区分"重试"和"重复调用"

重要:需要区分以下两种情况:

情况 A: 认证重试(正常)

[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED  ← 只有一次 CALL STARTED
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...  ← 第 1 次尝试
[QwenAgentManager] ❌ Authentication attempt 1 failed
[QwenAgentManager] ⏳ Retrying in 1000ms...
[QwenAgentManager] 📝 Authenticating (attempt 2/3)...  ← 第 2 次尝试
[QwenAgentManager] ✅ Authentication successful on attempt 2

这是正常的! 这是同一个认证调用的多次尝试。

情况 B: 重复认证调用(异常)

[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at ...  ← 第 1 个认证调用
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...
[QwenAgentManager] ✅ Authentication successful on attempt 1
[QwenAgentManager] 🔐 AUTHENTICATION CALL STARTED at ...  ← 第 2 个认证调用!❌
[QwenAgentManager] 📝 Authenticating (attempt 1/3)...

这是异常的! authenticateWithRetry() 被调用了两次。

4. 检查 agentInitialized 标志

查找以下日志:

[WebViewProvider] Agent already initialized, reusing existing connection

如果每次打开都看到 "Starting initialization",说明标志没有正确保持。

5. 检查是否是 OAuth 流程本身的问题

如果日志显示只有一次 "AUTHENTICATION CALL STARTED",但浏览器弹出了两次授权页面,那可能是 Qwen CLI 的 OAuth 流程本身需要两次交互

这种情况需要检查 Qwen CLI 的实现,不是 VSCode 扩展的问题。

🔧 手动测试步骤

测试 1: 正常流程

1. 清除缓存: Cmd+Shift+P → "Clear Authentication Cache"
2. 打开 Chat UI
3. 应该看到: 登录提示 (1)
4. 关闭 Chat UI
5. 重新打开 Chat UI
6. 应该看到: 直接连接,不需要登录 ✅

测试 2: 缓存过期

1. 修改 AUTH_CACHE_DURATION 为 1 分钟:
   // AuthStateManager.ts:21
   private static readonly AUTH_CACHE_DURATION = 1 * 60 * 1000;

2. 打开 Chat UI → 登录
3. 等待 2 分钟
4. 重新打开 Chat UI
5. 应该看到: 需要重新登录 (1)

测试 3: 清除缓存

1. 打开 Chat UI (已登录)
2. 执行: "Clear Authentication Cache"
3. 关闭 Chat UI
4. 重新打开 Chat UI
5. 应该看到: 需要重新登录 (1)

📊 认证状态管理

缓存存储位置

macOS:   ~/Library/Application Support/Code/User/globalStorage/
Linux:   ~/.config/Code/User/globalStorage/
Windows: %APPDATA%\Code\User\globalStorage\

缓存内容

{
  isAuthenticated: true,
  authMethod: "qwen-oauth",  // 或 "openai"
  workingDir: "/path/to/workspace",
  timestamp: 1700000000000  // Unix timestamp
}

缓存有效期

  • 默认: 24 小时
  • 修改方式: 编辑 AuthStateManager.ts:21
  • 检查方式: 执行命令(如果添加了)或查看日志

🎯 关键代码位置

功能 文件 行号
认证缓存管理 AuthStateManager.ts 全文
认证逻辑 QwenAgentManager.ts 61-195
初始化控制 WebViewProvider.ts 113-154
清除缓存命令 extension.ts 148-160
缓存有效期 AuthStateManager.ts 21

总结

当前实现已经修复了重复登录的问题

  1. 使用 needsAuth 标志确保最多认证一次
  2. 缓存有效时跳过认证
  3. Session 恢复成功时跳过认证
  4. 清除缓存时重置 agentInitialized 标志
  5. 缓存失效时自动重新认证(只一次)

如果仍然遇到多次登录,请:

  1. 检查日志确认是否真的登录了多次
  2. 确认是否是重试机制3 次尝试是正常的)
  3. 检查是否多次打开了不同的 Chat UI 实例
  4. 提供详细的日志帮助诊断

最后更新: 2025-11-17