假设我们有一个应用程序想要访问流行的俄罗斯社交网络VK并使用WinForms GUI在C#上编写。 VK使用类似OAuth2的方法,因此我们需要使用vk oauth授权URL打开Web浏览器。然后我们订阅webBrowser的OnNavigated事件并等待,直到url与查询字符串中的访问令牌的某个预定义url不相等。
从现在开始,我们可以使用接收到的访问令牌调用vk方法,但是这里发生了一些奇怪的事情:当我尝试使用HttpClient.GetAsync(methodUri)调用一些vk方法时,一切都按计划进行,除了打开来自系统Web浏览器中的授权Web浏览器。
vk的客户端授权网址看起来像https://oauth.vk.com/authorize?client_id={clientId}&scope={scope}&redirect_uri=https://oauth.vk.com/blank.html&display={displayType}&response_type=token
,已收到accessToken的网址看起来像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 code:
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=....
。
我不知道为什么会发生这种情况,但我担心数字会出现。
重要的补充:只有当Web浏览器没有关于会话的信息或者它已过期时才会发生这种情况,也就是说,我必须在vk的登录表单中输入用户名和密码。如果cookie包含必要的信息,并且它会自动重定向到包含其中的令牌的页面(再次带有#
符号),一切都按预期工作