Golang从Webview中获取Cookies的方法

Golang从Webview中获取Cookies的方法 我正在编写一个Go组件,并希望在启动时提供个人用户登录功能。理想情况下,这应该通过一个webview来完成,该webview在程序启动时被拉起。这个webview应该连接到一个独立于我的程序的身份服务器。如果登录成功,响应中会设置一个包含访问令牌和刷新令牌的cookie。此时,我希望webview关闭,并从cookie中提取令牌以供Go程序使用。

我曾尝试使用webview库zserge/webview来实现这一点。然而,我还没有找到使用这个库提取cookie的方法。内置库net/http具有检索cookie的功能——但是,zserge/webview库似乎没有使用内置的net/http库。

这可能实现吗?


更多关于Golang从Webview中获取Cookies的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

或许开个问题去问问编写这个库的人。

更多关于Golang从Webview中获取Cookies的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中从webview获取cookies确实是一个常见需求。对于zserge/webview库,由于它使用系统原生webview组件,无法直接访问cookies。不过可以通过JavaScript注入和本地HTTP服务器的方式实现。

以下是两种可行的解决方案:

方案1:使用JavaScript注入获取cookies

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
	"github.com/zserge/webview"
)

func main() {
	// 创建本地HTTP服务器来接收cookies
	http.HandleFunc("/cookies", func(w http.ResponseWriter, r *http.Request) {
		cookies := r.URL.Query()["cookie"]
		for _, cookie := range cookies {
			fmt.Printf("Received cookie: %s\n", cookie)
			// 这里可以解析cookie并提取令牌
		}
		w.Write([]byte("OK"))
	})
	
	go http.ListenAndServe(":8080", nil)
	
	// 创建webview
	w := webview.New(webview.Settings{
		Title: "登录",
		URL:   "https://your-auth-server.com/login",
		Width:  800,
		Height: 600,
		ExternalInvokeCallback: func(w webview.WebView, data string) {
			// 从JavaScript接收数据
			fmt.Printf("Received from JS: %s\n", data)
			// 这里可以处理cookies
			w.Terminate()
		},
	})
	
	// 注入JavaScript来监控登录成功和获取cookies
	w.Init(`
		// 监控登录成功
		function checkLoginSuccess() {
			// 根据你的登录页面实际情况调整这个条件
			if (window.location.href.includes('login-success') || 
				document.body.innerText.includes('登录成功')) {
				
				// 获取所有cookies
				var cookies = document.cookie;
				
				// 发送到Go程序
				external.invoke(cookies);
				
				// 或者发送到本地服务器
				fetch('http://localhost:8080/cookies?cookie=' + encodeURIComponent(cookies));
			}
		}
		
		// 定期检查登录状态
		setInterval(checkLoginSuccess, 1000);
		
		// 或者监听页面变化
		window.addEventListener('load', checkLoginSuccess);
	`)
	
	w.Run()
}

方案2:使用gowebview库(支持cookies访问)

package main

import (
	"fmt"
	"net/http"
	"net/url"
	"time"
	"github.com/wailsapp/wails/v2/pkg/runtime"
	"github.com/wailsapp/wails/v2"
)

type App struct {
	ctx context.Context
}

func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
	
	// 创建webview窗口
	runtime.WindowExecJS(a.ctx, `
		// 加载登录页面
		window.location.href = 'https://your-auth-server.com/login';
		
		// 监听页面加载完成
		window.addEventListener('load', function() {
			// 获取cookies
			var cookies = document.cookie;
			
			// 发送回Go
			window.go.main.App.HandleCookies(cookies).then(() => {
				// 关闭窗口
				window.close();
			});
		});
	`)
}

func (a *App) HandleCookies(cookies string) {
	fmt.Printf("Received cookies: %s\n", cookies)
	
	// 解析cookies
	req := &http.Request{Header: http.Header{"Cookie": []string{cookies}}}
	parsedCookies := req.Cookies()
	
	for _, cookie := range parsedCookies {
		fmt.Printf("Cookie: %s = %s\n", cookie.Name, cookie.Value)
		// 提取访问令牌和刷新令牌
		if cookie.Name == "access_token" {
			// 保存访问令牌
		}
		if cookie.Name == "refresh_token" {
			// 保存刷新令牌
		}
	}
}

func main() {
	app := &App{}
	
	err := wails.Run(&wails.AppConfig{
		Width:  800,
		Height: 600,
		Title:  "登录",
		JS:     "",
		CSS:    "",
		Colour: "#131313",
		Assets: wails.Assets{},
		Bind: []interface{}{
			app,
		},
	})
	
	if err != nil {
		fmt.Println("Error:", err)
	}
}

方案3:使用自定义HTTP客户端和cookie jar

package main

import (
	"fmt"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"time"
	"github.com/zserge/webview"
)

func main() {
	// 创建cookie jar来存储cookies
	jar, _ := cookiejar.New(nil)
	client := &http.Client{
		Jar: jar,
		Timeout: 30 * time.Second,
	}
	
	// 启动webview
	w := webview.New(webview.Settings{
		Title: "登录",
		URL:   "https://your-auth-server.com/login",
		Width:  800,
		Height: 600,
	})
	
	// 在webview关闭后,使用HTTP客户端访问相同URL获取cookies
	w.Run()
	
	// webview关闭后,使用相同的HTTP客户端访问页面获取cookies
	resp, err := client.Get("https://your-auth-server.com/login")
	if err == nil {
		defer resp.Body.Close()
		
		// 获取该URL的cookies
		u, _ := url.Parse("https://your-auth-server.com")
		cookies := jar.Cookies(u)
		
		for _, cookie := range cookies {
			fmt.Printf("Cookie: %s=%s\n", cookie.Name, cookie.Value)
		}
	}
}

方案4:使用Chrome DevTools Protocol(CDP)

package main

import (
	"context"
	"fmt"
	"time"
	"github.com/chromedp/chromedp"
)

func main() {
	// 创建chrome实例
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()
	
	// 设置超时
	ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
	defer cancel()
	
	var cookies string
	
	// 运行任务
	err := chromedp.Run(ctx,
		// 导航到登录页面
		chromedp.Navigate("https://your-auth-server.com/login"),
		
		// 等待登录完成(根据实际情况调整选择器)
		chromedp.WaitVisible("#login-success", chromedp.ByID),
		
		// 获取cookies
		chromedp.ActionFunc(func(ctx context.Context) error {
			cookiesObj, err := chromedp.RunResponse(ctx,
				chromedp.Tasks{
					chromedp.Evaluate(`document.cookie`, &cookies),
				},
			)
			if err != nil {
				return err
			}
			
			// 也可以通过cookiesObj获取
			fmt.Printf("Cookies from document: %s\n", cookies)
			return nil
		}),
	)
	
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	
	// 解析和使用cookies
	fmt.Printf("Final cookies: %s\n", cookies)
}

推荐使用方案1或方案4。方案1适用于简单的webview集成,方案4提供了更完整的浏览器控制能力。如果使用zserge/webview,方案1的JavaScript注入是最直接的实现方式。

回到顶部