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

379 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 导致重复认证(已修复)
**之前的代码**
```typescript
try {
if (switchSession fails) {
authenticate(); // 第 1 次
} else {
authenticate(); // 第 1 次
}
} catch {
authenticate(); // 第 2 次!❌
}
```
**修复后的代码**
```typescript
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`,导致不会重新初始化。
**修复方案**
```typescript
// 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: 正常流程
```bash
1. 清除缓存: Cmd+Shift+P → "Clear Authentication Cache"
2. 打开 Chat UI
3. 应该看到: 登录提示 (1)
4. 关闭 Chat UI
5. 重新打开 Chat UI
6. 应该看到: 直接连接,不需要登录 ✅
```
### 测试 2: 缓存过期
```bash
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: 清除缓存
```bash
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\
```
### 缓存内容
```typescript
{
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