2

假设我们有一个应用程序想要访问流行的俄罗斯社交网络 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 中包含令牌的页面(#再次带有符号),则一切都按预期工作

4

0 回答 0