问题是我previous question的延续。问题的简短解释:我试图在WinForms应用程序中使用WebBrowser在vk.com上使用类似OAuth2的方法授权用户,因此我需要在webBrowser中打开特定于应用程序的URL,并且vk.com将重定向到授权页面。授权后,vk.com会重定向到https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
我可以获取令牌并将其与vk.com API一起使用。一切都很好,除了在授权后不同时间在浏览器中打开的奇数页面(带有URL https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId}%20-%20#access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
)。
我有点重做样本,现在如果在处理WebBrowwser(AuthenticationForm - > authenticationBrowser_DocumentCompleted)控件后出现GC.WaitForPendingFinalizers(); GC.Collect();
并且在另一种情况下打开,则页面无法在系统浏览器中打开。
重要:只有当必须填写授权表单时,错误才会显示,即Web浏览器不包含有效的会话数据。丢弃会话可以转到设置 - >您网页的安全性 - >看活动的历史 - >关闭所有会议
mainForm代码:
public partial class Form1 : Form
{
private string _token;
private readonly Uri _redirectUri = new Uri("https://oauth.vk.com/blank.html");
private readonly Uri _request = new Uri("https://api.vk.com/method/users.get.xml?user_ids=1&fields=online");
private readonly Uri _authorizationUri =
new Uri("https://oauth.vk.com/authorize?client_id=3836576&scope=8&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token");
public Form1()
{
InitializeComponent();
}
private async void loginButton_Click(object sender, EventArgs e)
{
var authenticationForm = new AuthenticationForm();
authenticationForm.Show();
_token = await Authenticate(authenticationForm.GetToken);
authenticationForm.Close();
}
private async Task<string> Authenticate(Func<Uri, Uri, Task<string>> aunthenticationResultGetter)
{
var token = await aunthenticationResultGetter(_authorizationUri, _redirectUri);
//...
return token;
}
private async void doRequestButton_Click(object sender, EventArgs e)
{
//assume, we using token here
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(_request);
var responseString = await response.Content.ReadAsStringAsync();
outputTextBox.AppendText(responseString);
}
}
authenticationForm代码:
public partial class AuthenticationForm : Form
{
private readonly TaskCompletionSource<string> _tokenCompletitionSource = new TaskCompletionSource<string>();
private Uri _redirectUri;
private WebBrowser _authenticationBrowser;
public AuthenticationForm()
{
InitializeComponent();
}
public async Task<string> GetToken(Uri authUri, Uri redirectUri)
{
_redirectUri = redirectUri;
_authenticationBrowser = new WebBrowser
{
Dock = DockStyle.Fill,
Location = new System.Drawing.Point(0, 0),
MinimumSize = new System.Drawing.Size(20, 20),
Name = "authenticationBrowser",
ScriptErrorsSuppressed = true,
Size = new System.Drawing.Size(641, 353),
TabIndex = 0
};
_authenticationBrowser.DocumentCompleted += authenticationBrowser_DocumentCompleted;
_authenticationBrowser.Navigate(authUri);
Controls.Add(_authenticationBrowser);
var token = await _tokenCompletitionSource.Task;
return token;
}
private void authenticationBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (!(_redirectUri.IsBaseOf(e.Url) && _redirectUri.AbsolutePath.Equals(e.Url.AbsolutePath))) return;
_authenticationBrowser.Dispose();
//GC.WaitForPendingFinalizers();
//GC.Collect();
var token = e.Url.ToString().Split('=')[1].Split('&')[0];
_tokenCompletitionSource.SetResult(token);
}
}
答案 0 :(得分:0)
我也遇到了与box.com api OAuth集成到我的WPF应用程序中的类似问题。但是box.com api提供的WPF示例没有任何问题。
即使我更改了官方示例的逻辑和流程以匹配我的WPF应用程序,我也无法重现该问题。
最后我通过在导航事件中添加“about:blank”导航来修复该问题,如下所示,我正在共享代码以便它可以帮助某些人。
private void browserAuthentication_Navigating(object sender, NavigatingCancelEventArgs e)
{
if(e.Uri.Host.Equals( _callbackUri.Host))
{
e.Cancel = true;
//This code is required. Otherwise the box api navigation will popup an external browser window.
browserAuthentication.Navigate("about:blank");
this._authenticationResponseValues = GetQueryOptions(e.Uri);
}
}
private IDictionary<string, string> GetQueryStringParamAndValues(Uri resultUri)
{
string[] queryParams = null;
var queryValues = new Dictionary<string, string>();
int fragmentIndex = resultUri.AbsoluteUri.IndexOf("#", StringComparison.Ordinal);
if (fragmentIndex > 0 && fragmentIndex < resultUri.AbsoluteUri.Length + 1)
{
queryParams = resultUri.AbsoluteUri.Substring(fragmentIndex + 1).Split('&');
}
else if (fragmentIndex < 0)
{
if (!string.IsNullOrEmpty(resultUri.Query))
{
queryParams = resultUri.Query.TrimStart('?').Split('&');
}
}
if (queryParams != null)
{
foreach (var param in queryParams)
{
if (!string.IsNullOrEmpty(param))
{
string[] kvp = param.Split('=');
queryValues.Add(kvp[0], System.Net.WebUtility.UrlDecode(kvp[1]));
}
}
}
return queryValues;
}