2014-03-31 43 views
0

問題是我的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一起使用。除了在授權後的不同時間在瀏覽器中打開的奇怪頁面(網址爲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();,並且在另一種情況下打開,則我有點返工示例,現在該頁面在系統瀏覽器中不打開。處置WebBrowser控件導致在系統瀏覽器中打開新頁面

重要提示:該錯誤僅在必須填寫授權表單時出現,即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); 
    } 
} 

here is full project code

+0

您確定同一個'{accessToken}'令牌可以在不同的HTTP會話上使用嗎?服務器可以控制這個,而不是客戶端(除非您設法複製會話身份1:1,這不僅僅是複製cookie)。您需要使用Fiddler研究會話流量。 – Noseratio

+0

@Noseratio,vk.com api文檔中的某個地方告訴記錄不綁定到http會話,它只綁定到ip。 –

+0

我不認爲這只是IP地址。想想一個典型的網絡是在一個真實的IP後面進行NAT的。無論如何,**不要在自己的事件處理程序**中部署'_authenticationBrowser'。推遲''form.BeginInvoke'處置。 – Noseratio

回答

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; 
} 
相關問題