From d05c19a8d5d61a690c07ff6df64320bcd2494f1c Mon Sep 17 00:00:00 2001 From: kyx236 Date: Sun, 1 Feb 2026 09:19:53 +0800 Subject: [PATCH] feat: Add chromedp and rod-based OAuth authorization methods. --- backend/internal/auth/chromedp.go | 78 ++++++++++++++++++------------- backend/internal/auth/rod.go | 6 ++- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/backend/internal/auth/chromedp.go b/backend/internal/auth/chromedp.go index 31eed14..e9b27b6 100644 --- a/backend/internal/auth/chromedp.go +++ b/backend/internal/auth/chromedp.go @@ -49,41 +49,49 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool ctx, cancel := chromedp.NewContext(allocCtx) defer cancel() - ctx, cancel = context.WithTimeout(ctx, 120*time.Second) + // 增加超时时间到 180 秒 + ctx, cancel = context.WithTimeout(ctx, 180*time.Second) defer cancel() var callbackURL string - chromedp.ListenTarget(ctx, func(ev interface{}) { - switch ev := ev.(type) { - case *fetch.EventRequestPaused: - // Fetch domain pauses requests; we must continue them to avoid stalling navigation. - reqID := ev.RequestID - go func() { _ = fetch.ContinueRequest(reqID).Do(ctx) }() + // 只在代理需要认证时才启用 Fetch 域 + if proxyServer != "" && proxyUser != "" { + chromedp.ListenTarget(ctx, func(ev interface{}) { + switch ev := ev.(type) { + case *fetch.EventRequestPaused: + // Fetch domain pauses requests; we must continue them to avoid stalling navigation. + reqID := ev.RequestID + go func() { _ = fetch.ContinueRequest(reqID).Do(ctx) }() - case *fetch.EventAuthRequired: - reqID := ev.RequestID - source := fetch.AuthChallengeSourceServer - if ev.AuthChallenge != nil { - source = ev.AuthChallenge.Source - } - - go func() { - resp := &fetch.AuthChallengeResponse{Response: fetch.AuthChallengeResponseResponseDefault} - if source == fetch.AuthChallengeSourceProxy { - if proxyUser != "" { - resp.Response = fetch.AuthChallengeResponseResponseProvideCredentials - resp.Username = proxyUser - resp.Password = proxyPass - } else { - // Fail fast if the proxy requires auth but user didn't provide credentials. - resp.Response = fetch.AuthChallengeResponseResponseCancelAuth - } + case *fetch.EventAuthRequired: + reqID := ev.RequestID + source := fetch.AuthChallengeSourceServer + if ev.AuthChallenge != nil { + source = ev.AuthChallenge.Source } - _ = fetch.ContinueWithAuth(reqID, resp).Do(ctx) - }() - case *network.EventRequestWillBeSent: + go func() { + resp := &fetch.AuthChallengeResponse{Response: fetch.AuthChallengeResponseResponseDefault} + if source == fetch.AuthChallengeSourceProxy { + if proxyUser != "" { + resp.Response = fetch.AuthChallengeResponseResponseProvideCredentials + resp.Username = proxyUser + resp.Password = proxyPass + } else { + // Fail fast if the proxy requires auth but user didn't provide credentials. + resp.Response = fetch.AuthChallengeResponseResponseCancelAuth + } + } + _ = fetch.ContinueWithAuth(reqID, resp).Do(ctx) + }() + } + }) + } + + // 监听回调 URL + chromedp.ListenTarget(ctx, func(ev interface{}) { + if ev, ok := ev.(*network.EventRequestWillBeSent); ok { url := ev.Request.URL if strings.Contains(url, "localhost") && strings.Contains(url, "code=") { callbackURL = url @@ -91,13 +99,19 @@ func CompleteWithChromedp(authURL, email, password, teamID string, headless bool } }) - err := chromedp.Run(ctx, - // Handle proxy auth (407) in headless mode. - fetch.Enable().WithHandleAuthRequests(true), + // 构建运行任务 + tasks := []chromedp.Action{ network.Enable(), chromedp.Navigate(authURL), chromedp.WaitReady("body"), - ) + } + + // 只在代理需要认证时才启用 Fetch 域 + if proxyServer != "" && proxyUser != "" { + tasks = append([]chromedp.Action{fetch.Enable().WithHandleAuthRequests(true)}, tasks...) + } + + err := chromedp.Run(ctx, tasks...) if err != nil { return "", fmt.Errorf("访问失败: %v", err) } diff --git a/backend/internal/auth/rod.go b/backend/internal/auth/rod.go index cebfdd3..90c2a45 100644 --- a/backend/internal/auth/rod.go +++ b/backend/internal/auth/rod.go @@ -123,7 +123,8 @@ func (r *RodAuth) Close() { func (r *RodAuth) CompleteOAuth(authURL, email, password, teamID string) (string, error) { // Handle proxy auth (407) in headless mode. // When Fetch domain is enabled without patterns, requests will be paused and must be continued. - if r.proxy != "" { + // 只在代理需要认证时才启用 Fetch 域 + if r.proxy != "" && r.proxyUser != "" { authBrowser, cancel := r.browser.WithCancel() defer cancel() @@ -160,7 +161,8 @@ func (r *RodAuth) CompleteOAuth(authURL, email, password, teamID string) (string } defer page.Close() - page = page.Timeout(45 * time.Second) + // 增加超时时间到 90 秒 + page = page.Timeout(90 * time.Second) if err := page.Navigate(authURL); err != nil { return "", fmt.Errorf("访问授权URL失败: %v", err)