Подтвердить что ты не робот

Facebook OAuth в WPF и С# Пример

Я разрабатываю приложение WPF, которое требует от меня получить токен доступа из Facebook с использованием oAuth. После долгих поисков в Интернете я пришел к следующим выводам:

  • OAuth должен быть выполнен в браузере
  • Мне нужно посмотреть URL-адреса в этом браузере, поэтому он должен быть внутри WebBrowser Управление WPF

Я решил создать Modal Dialog для аутентификации Facebook, и я могу просто взять токен доступа и игнорировать остальные. Я хотел сохранить модель MVVM, но это было сложнее, чем я ожидал. Любые идеи о том, как это сделать, будут очень полезны.

Вот некоторые функции, которые я реализовал

  • Удаление файлов cookie, поэтому может потребоваться аутентификация другого пользователя без необходимости регистрации текущего пользователя
  • Отключить создание новой учетной записи, поскольку это привело к странному опыту пользовательского интерфейса.
  • Прослушивание кнопки отмены из javascript, сгенерированного Facebook

Окно WPF

WPF очень прост. По сути, это просто элемент управления WebBrowser с подключенными событиями Navigated and Navigating.

<Window x:Class="FacebookAuthenticator.FacebookAuthenticationWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Authenticate Facebook" 
        Height="600" 
        Width="600" 
        ResizeMode="NoResize" 
        WindowStyle="ToolWindow">
<Grid>
    <WebBrowser Name="webBrowser" 
                Navigated="webBrowser_Navigated" 
                Navigating="webBrowser_Navigating" />
</Grid>

Код

//The Application ID from Facebook
public string AppID {get; set; }

//The access token retrieved from facebook authentication
public string AccessToken {get; set; }

public FacebookAuthenticationWindow()
{
    InitializeComponent();
    this.Loaded += (object sender, RoutedEventArgs e) =>
    {
        //Add the message hook in the code behind since I got a weird bug when trying to do it in the XAML
        webBrowser.MessageHook += webBrowser_MessageHook;

        //Delete the cookies since the last authentication
        DeleteFacebookCookie();

        //Create the destination URL
        var destinationURL = String.Format("https://www.facebook.com/dialog/oauth?client_id={0}&scope={1}&display=popup&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token",
           AppID, //client_id
           "email,user_birthday" //scope
        );
        webBrowser.Navigate(destinationURL);
    };
}

Получение токена доступа

Я точно забыл, где я получил этот код (если кто-то может напомнить мне, чтобы я мог отдать должное, я был бы благодарен).

private void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    //If the URL has an access_token, grab it and walk away...
    var url = e.Uri.Fragment;
    if (url.Contains("access_token") && url.Contains("#"))
    {
        url = (new System.Text.RegularExpressions.Regex("#")).Replace(url, "?", 1);
        AccessToken = System.Web.HttpUtility.ParseQueryString(url).Get("access_token");
        DialogResult = true;
        this.Close();
    }
}

Удаление файлов cookie

Я понял, что после того, как кто-то вошел в систему, статус остался таким и не разрешил кому-то еще войти. Я решил удалить файлы cookie в начале каждой проверки подлинности, чтобы предотвратить это.

private void DeleteFacebookCookie()
{
    //Set the current user cookie to have expired yesterday
    string cookie = String.Format("c_user=; expires={0:R}; path=/; domain=.facebook.com", DateTime.UtcNow.AddDays(-1).ToString("R"));
    Application.SetCookie(new Uri("https://www.facebook.com"), cookie);
}

Нет новых учетных записей

Разрешение пользователю создать новую учетную запись привело к странному опыту пользовательского интерфейса. Для моих случаев использования пользователь должен иметь уже существующую учетную запись. Я отключил это, проверив, был ли пользователь перенаправлен на "r.php/", который использует Facebook для создания новой учетной записи.

private void webBrowser_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
{
    if (e.Uri.LocalPath == "/r.php")
    {
        MessageBox.Show("To create a new account go to www.facebook.com", "Could Not Create Account", MessageBoxButton.OK, MessageBoxImage.Error);
        e.Cancel = true;
    }
}

Обработка окна .close()

Кнопка "Отмена" в диалоговом окне "Facebook" позволяет закрыть окно. Мне нужно было поймать это и не забудьте закрыть окно. Я понятия не имел, как, но я видел, что в MessageHook я смог увидеть, что последнее сообщение, которое нужно отправить (int msg), каждый раз составляло 130, поэтому я просто слушал 130. Это неряшливо, но оно работает.

IntPtr webBrowser_MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    //msg = 130 is the last call for when the window gets closed on a window.close() in javascript
    if (msg == 130)
    {
        this.Close();
    }
    return IntPtr.Zero;
}

Резюме

Использование кода довольно просто

FacebookAuthenticationWindow dialog = new FacebookAuthenticationWindow() { AppID = "YOURAPPID" };
if(dialog.ShowDialog() == true)
{
    string accessToken = dialog.AccessToken;
    //The world is your oyster
}

Я надеюсь, что этот пример полезен для сообщества. Мне бы очень хотелось услышать от всех, кто имеет какие-либо улучшения, идеи или даже критику.

~ Мо

4b9b3361