.NET兼职社区
.NET兼职社区
.NET兼职社区
.NET兼职社区
.NET兼职社区
.NET兼职社区
我实现的方式有三种,一种是通过JS注入cookie的方式,第二种是通过读取本地化存储的用户数据实现,第三种是发送请求的时候,对请求头进行修改。
一、JS注入的方式
这种方式需要逆向分析下需要的参数,对不熟悉JS逆向的不是很友好。
这里给出参考代码。
点击按钮,跳转到指定的url,页面加载完成后,注入JS。代码中有注释。
csharp
private void ButtonGo_Click(object sender, RoutedEventArgs e)
{
if (webView != null && webView.CoreWebView2 != null)
{
webView.CoreWebView2.NavigationCompleted += ActionCompleted;
webView.CoreWebView2.Navigate(addressBar.Text);
}
}
#region 可以成功实现cookie登录
private async void ActionCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
{
string cookieString = $"document.cookie='{_cookie}';";
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(cookieString); //通过js注入cookie 这种方式注入完成后需要刷新页面
// 刷新页面 isLoadCookie 表示cookie加载完成后就不要再重定向了 避免事件链无限触发
if (!isLoadCookie)
{
webView.CoreWebView2.Navigate(addressBar.Text);
}
//加载完成
isLoadCookie = true;
}
#endregion
二、读取用户本地化数据
这种方式是比较简单的方式,不需要分析别人网页,无脑加载就行。适合不想麻烦的人。
csharp
#region 成功实现cookie登录 。用户数据存储 通过指定用户数据目录的存储和加载。也可以实现自动登录,如果你之前登录过,WebView2会把登录的用户信息存储在userDataFolder中,下次再指定相同的文件,WebView2会自动获取用户数据。如果想实现用户切换,可以为每个用户独立一个UserData文件夹,切换的时候加载不同的文件夹,就OK。
string userDataFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WebView2", "UserData");
Directory.CreateDirectory(userDataFolder); // 确保目录存在
var environment = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
await webView.EnsureCoreWebView2Async(environment);
#endregion
这种方式是在你初始化的时候去加载指定的环境,EnsureCoreWebView2Async
函数用于初始化WebView2,如果不指定环境,默认传null就行,webView会用默认环境加载。注释也写的毕竟详细,可以根据注释参考调整。
三、通过注入请求过滤器,通过请求头注入cookie
这种方式也需要分析请求头,和一些决定性参数。
csharp
// 注册过滤器,这里假设我们对所有HTTP和HTTPS请求都感兴趣 https://www.bilibili.com/*
webView.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);
webView.CoreWebView2.WebResourceRequested += delegate (
object? sender, CoreWebView2WebResourceRequestedEventArgs args)
{
CoreWebView2WebResourceContext resourceContext = args.ResourceContext;
// 只拦截文档资源
if (resourceContext != CoreWebView2WebResourceContext.Document)
{
return;
}
if (!args.Request.Uri.Contains("bilibili")) return;
CoreWebView2HttpRequestHeaders requestHeaders = args.Request.Headers;
//foreach (var item in requestHeaders)
//{
// await LogService.Instance.WriteInfoLog($"{item.Key}:{item.Value.ToString()}");
//}
requestHeaders.SetHeader("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
requestHeaders.SetHeader("cookie", ";;domain=.bilibili.com;path=/");
requestHeaders.SetHeader("sec-ch-ua", "\"Chromium\";v=\"130\", \"Microsoft Edge\";v=\"130\", \"Not ? A_Brand\";v=\"99\", \"Microsoft Edge WebView2\";v=\"130\"");
requestHeaders.SetHeader("sec-ch-ua-mobile", "?0");
requestHeaders.SetHeader("sec-ch-ua-platform", "\"Windows\"");
requestHeaders.SetHeader("upgrade-insecure-requests", "1");
requestHeaders.SetHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0");
Console.WriteLine();
初始化的时候添加请求过滤器,然后对符合要求的url动手。应该可以实现。修改请求头后再去加载网页。
四、WebView2一些常用的方法
4.1页面和后端进行通信
csharp
//当 CoreWebView2 控件接收到从网页发送的消息时,这个方法会被调用
webView.CoreWebView2.WebMessageReceived += UpdateAddressBar;
/**
* AddScriptToExecuteOnDocumentCreatedAsync 方法:
这个方法用于向 WebView2 控件注入一段 JavaScript 代码,这段代码会在每个新文档创建时自动执行。
注入的脚本会在每个页面加载完成后立即运行,适用于所有新加载的页面。
注入的 JavaScript 代码:
"window.chrome.webview.postMessage(window.document.URL);"
这段代码的作用是获取当前页面的 URL,并通过 postMessage 方法将 URL 发送到 WebView2 控件。
window.chrome.webview.postMessage 是 WebView2 提供的一个 API,用于从网页向宿主应用程序发送消息。
* **/
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
/**
* AddScriptToExecuteOnDocumentCreatedAsync 方法:
同上,这个方法用于向 WebView2 控件注入一段 JavaScript 代码,这段代码会在每个新文档创建时自动执行。
注入的 JavaScript 代码:
"window.chrome.webview.addEventListener('message', event => alert(event.data));"
这段代码的作用是为 window.chrome.webview 对象添加一个消息事件监听器。
当从宿主应用程序(即 WPF 应用程序)通过 PostWebMessageAsJson 或 PostWebMessageAsString 方法发送消息到网页时,这个监听器会被触发。
event.data 包含从宿主应用程序发送的消息内容,alert(event.data) 会弹出一个警告框显示接收到的消息。
* **/
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(event.data));");
csharp
void UpdateAddressBar(object sender, CoreWebView2WebMessageReceivedEventArgs args)
{
String uri = args.TryGetWebMessageAsString();
addressBar.Text = uri;
//给页面发送消息
webView.CoreWebView2.PostWebMessageAsString(uri);
}
通信过程,页面加载,页面会向后端发送消息,后端收到消息触发UpdateAddressBar函数,然后后端发消息给页面,页面收到消息,弹框。
前端代码:
csharp
<Window x:Class="MyWpfDotnetCoreWv2App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MyWpfDotnetCoreWv2App"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!--<DockPanel>
<wv2:WebView2 Name="webView"
Source="https://www.bilibili.com/"
/>
</DockPanel>-->
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<Button x:Name="ButtonGo" DockPanel.Dock="Right" Click="ButtonGo_Click" Content="Go"/>
<Button x:Name="ButtonGetCookie" DockPanel.Dock="Right" Click="ButtonGetCookie_Click" Content="GetCookie"/>
<TextBox Name = "addressBar"/>
</DockPanel>
<wv2:WebView2 Name = "webView" />
</DockPanel>
</Window>