假设我们有一个应用程序想要访问流行的俄罗斯社交网络 VK,并使用 WinForms GUI 用 C# 编写。VK 使用类似于 OAuth2 的方法,因此我们需要使用 vk oauth 授权 url 打开 Web 浏览器。然后我们订阅 webBrowser 的 OnNavigated 事件并等到 url 不等于某个预定义的 url 和查询字符串中的访问令牌。从现在开始,我们可以使用接收到的访问令牌调用 vk 方法,但是这里发生了一些奇怪的事情:当我尝试使用 HttpClient.GetAsync(methodUri) 调用一些 vk 方法时,一切都按计划进行,除了从系统 Web 浏览器中的授权 Web 浏览器。vk 的客户端授权 Url 看起来像https://oauth.vk.com/authorize?client_id={clientId}&scope={scope}&redirect_uri=https://oauth.vk.com/blank.html&display={displayType}&response_type=token
,带有收到 accessToken 的 Url 看起来像https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
,注意问号上的数字符号。
主要形式的代码:
var authenticationForm = new AuthenticationForm();
authenticationForm.Show();
_authenticatedUser = await application.ClientAuthenticator.Authenticate(authenticationForm.GetToken);
authenticationForm.Close();
var httpClient = new HttpClient();
var request = "https://api.vk.com/method/users.get.xml?user_ids=1&fields=online";
var response = await httpClient.GetAsync(request);
authenticationForm类代码:
public partial class AuthenticationForm : Form
{
private readonly TaskCompletionSource<VkAccessToken> _tokenCompletitionSource = new TaskCompletionSource<VkAccessToken>();
private Uri _redirectUri;
public AuthenticationForm()
{
InitializeComponent();
}
public async Task<IVkAccessToken> GetToken(Uri authUri, Uri redirectUri)
{
authenticationBrowser.Navigate(authUri);
_redirectUri = redirectUri;
var token = await _tokenCompletitionSource.Task;
return token;
}
private async void authenticationBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
if (!(_redirectUri.IsBaseOf(e.Url) && _redirectUri.AbsolutePath.Equals(e.Url.AbsolutePath))) return;
//working with e.Url to achieve token, userId and expiresIn, creating token variable based on them
_tokenCompletitionSource.SetResult(token);
}
}
ClientAuthenticator.Authenticate 代码:
public async Task<IVkAuthenticatedUser> Authenticate(Func<Uri, Uri, Task<IVkAuthenticatedUser>> aunthenticationResultGetter)
{
var authorizationUri =
new Uri("https://oauth.vk.com/authorize?client_id={clientId}&scope={scope}&redirect_uri=https://oauth.vk.com/blank.html&display=page&response_type=token");
var token = await aunthenticationResultGetter(authorizationUri, _application.Settings.RedirectUri);
//...
return newUserBasedOnToken;
}
从主窗体退出(使用调试器)var response = await httpClient.GetAsync(request);
行后,我的系统浏览器打开链接,如https://oauth.vk.com/blank.html#access_token={accessToken}&expires_in={expiresIn}&user_id={userId} - #access_token={accessToken}&expires_in={expiresIn}&user_id={userId}
最近的 accessToken、expiresIn 和 userId 值。是的,... - #access_token=....
在 url 中。我不知道为什么会发生这种情况,但我担心数字符号。
重要的补充:只有当 Web 浏览器没有关于会话的信息或它已过期时才会发生,也就是说,我必须在 vk 的登录表单中输入用户名和密码。如果 cookie 包含必要的信息,并且它会自动重定向到其 url 中包含令牌的页面(#
再次带有符号),则一切都按预期工作