65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Facebook、Google 和 Microsoft 账户在 WP8.0 应用 (MVVM) 中进行身份验证

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2014年5月31日

CPOL

4分钟阅读

viewsIcon

14596

downloadIcon

2

本示例展示如何将 Windows Phone 8.0 应用连接到 Facebook、Google 和 Microsoft 账户。主要功能:登录/注销,以及一个包含反馈、社交网络分享、评论和电子邮件分享的关于页面。下载 C# (19.4 MB) 简介 … 继续阅读 →

本示例展示如何将 Windows Phone 8.0 应用连接到 Facebook、Google 和 Microsoft 账户。主要功能:登录/注销,以及一个包含反馈、社交网络分享、评论和电子邮件分享的关于页面。

下载 C# (19.4 MB)

引言

本示例展示如何将 Windows Phone 8.0 应用连接到 Facebook、Google 和 Microsoft 账户。

主要功能:登录/注销,以及一个包含反馈、社交网络分享、评论和电子邮件分享的关于页面。

构建示例

您只需要 Visual Studio 2012/Visual Studio 2013 和 Windows 8/Windows 8.1,均为 RTM 版本。

此示例需要安装 Live SDK (http://msdn.microsoft.com/en-US/onedrive/dn630256)。

描述

本示例展示如何将 Windows Phone 8.0 应用连接到 Facebook、Google 和 Microsoft 账户。

主要特点

  • 登录/注销(对于注销,我添加了一些变通方法来修复 SDK 的提供商注销!)
  • 关于页面,包含反馈、社交网络分享、评论和电子邮件分享(这里不重要,但包含在代码中)

注意:本示例使用了 MVVM LightCimbalino Windows Phone Toolkit

本示例使用了

对于每个提供商,都需要在其网站上获取应用 ID/客户端 ID/客户端密钥

对于 Google,请访问 https://console.developers.google.com/project 并创建一个新项目(APIs & auth > credentials)

对于 Facebook,请访问 https://developers.facebook.com/ 并创建一个新应用。

对于 Live SDK,请访问 https://account.live.com/developers/applications/index 并创建一个应用或使用现有应用

在开始之前,您应该修改 Constant 文件以添加客户端 ID / 客户端密钥 / 应用 ID,否则应用将失败!!

此文件位于 Resource 文件夹内。

  /// <summary> 
    /// Defines the constants strings used in the app. 
    /// </summary> 
    public class Constants 
    { 
        /// <summary> 
        /// The facebook app id. 
        /// </summary> 
        public const string FacebookAppId = "<app id>"; 
 
        /// <summary> 
        /// The google client identifier. 
        /// </summary> 
        public const string GoogleClientId = "<client id>"; 
 
        /// <summary> 
        /// The google token file name. 
        /// </summary> 
        public const string GoogleTokenFileName = "Google.Apis.Auth.OAuth2.Responses.TokenResponse-user"; 
 
        /// <summary> 
        /// The google client secret. 
        /// </summary> 
        public const string GoogleClientSecret = "<client secret>"; 
 
        /// <summary> 
        /// The microsoft client identifier. 
        /// </summary> 
        public const string MicrosoftClientId = "<client id>"; 
 
      ... 
    }

现在,让我们看看如何连接到每个提供商。为了方便,我创建了一个 SessionService 来使用提供商值来管理登录和注销,这很好,因为在 LoginView 中,我将按钮设置为同一个命令,并且为每个命令设置了命令参数中的提供商。这使得 LoginView 和 LoginViewModel 更清晰、更简单。另一个好处是,例如,如果我需要连接到我的服务器来接受用户,我可以在身份验证后在 Session Manager 中完成,而无需将代码添加到每个提供商。

创建的类

  • FacebookService 包含与 Facebook 账户身份验证相关的所有代码;
  • MicrosoftService 包含与 Microsoft 账户身份验证相关的所有代码;
  • GoogleService 包含与 Google 账户身份验证相关的所有代码;
  • SessionService 调用所请求提供商的登录或注销方法;

FacebookService 是

 /// <summary> 
    /// Defines the Facebook Service. 
    /// </summary> 
    public class FacebookService : IFacebookService 
    { 
        private readonly ILogManager _logManager; 
        private readonly FacebookSessionClient _facebookSessionClient; 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="FacebookService"/> class. 
        /// </summary> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public FacebookService(ILogManager logManager) 
        { 
            _logManager = logManager; 
            _facebookSessionClient = new FacebookSessionClient(Constants.FacebookAppId); 
        } 
 
        /// <summary> 
        /// The login sync. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception; 
            Session sessionToReturn = null; 
            try 
            { 
                var session = await _facebookSessionClient.LoginAsync("user_about_me,read_stream"); 
                sessionToReturn = new Session 
                { 
                    AccessToken = session.AccessToken, 
                    Id = session.FacebookId, 
                    ExpireDate = session.Expires, 
                    Provider = Constants.FacebookProvider 
                }; 
 
                return sessionToReturn; 
            } 
            catch (InvalidOperationException) 
            { 
                throw; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
            return sessionToReturn; 
        } 
 
        /// <summary> 
        /// Logouts this instance. 
        /// </summary> 
        public async void Logout() 
        { 
            Exception exception = null; 
            try 
            { 
                _facebookSessionClient.Logout(); 
 
                // clean all cookies from browser, is a workarround 
                await new WebBrowser().ClearCookiesAsync(); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
    }

注意:在注销时,我添加了一个变通方法来清除浏览器中的所有 cookie,否则在第一次登录时可以使用任何您想要的账户,但下次登录时将使用上次登录的账户。

GoogleService 是

/// <summary> 
    /// The google service. 
    /// </summary> 
    public class GoogleService : IGoogleService 
    { 
        private readonly ILogManager _logManager; 
        private readonly IStorageService _storageService; 
        private UserCredential _credential; 
        private Oauth2Service _authService; 
        private Userinfoplus _userinfoplus; 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="GoogleService" /> class. 
        /// </summary> 
        /// <param name="logManager">The log manager.</param> 
        /// <param name="storageService">The storage service.</param> 
        public GoogleService(ILogManager logManager, IStorageService storageService) 
        { 
            _logManager = logManager; 
            _storageService = storageService; 
        } 
 
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception = null; 
            try 
            { 
                // Oauth2Service.Scope.UserinfoEmail 
                _credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets 
                { 
                    ClientId = Constants.GoogleClientId, 
                    ClientSecret = Constants.GoogleClientSecret 
                }, new[] { Oauth2Service.Scope.UserinfoProfile }, "user", CancellationToken.None); 
                 
                var session = new Session 
                { 
                    AccessToken = _credential.Token.AccessToken, 
                    Provider = Constants.GoogleProvider, 
                    ExpireDate = 
                        _credential.Token.ExpiresInSeconds != null 
                            ? new DateTime(_credential.Token.ExpiresInSeconds.Value) 
                            : DateTime.Now.AddYears(1), 
                    Id = string.Empty 
                }; 
 
                return session; 
            } 
            catch (TaskCanceledException taskCanceledException) 
            { 
                throw new InvalidOperationException("Login canceled.", taskCanceledException); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
            return null; 
        } 
 
        /// <summary> 
        /// Gets the user information. 
        /// </summary> 
        /// <returns> 
        /// The user info. 
        /// </returns> 
        public async Task<Userinfoplus> GetUserInfo() 
        { 
            _authService = new Oauth2Service(new BaseClientService.Initializer() 
            { 
                HttpClientInitializer = _credential, 
                ApplicationName = AppResources.ApplicationTitle, 
            }); 
            _userinfoplus = await _authService.Userinfo.V2.Me.Get().ExecuteAsync(); 
 
            return _userinfoplus; 
        } 
 
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            await new WebBrowser().ClearCookiesAsync(); 
            if (_storageService.FileExists(Constants.GoogleTokenFileName)) 
            { 
                _storageService.DeleteFile(Constants.GoogleTokenFileName); 
            } 
        } 
    }

注意: 在 Google 提供商的注销操作中,没有注销方法,解决方案是清除所有 cookie 并删除登录操作中创建的文件。

 MicrosoftService 是

 /// <summary> 
    /// The microsoft service. 
    /// </summary> 
    public class MicrosoftService : IMicrosoftService 
    { 
        private readonly ILogManager _logManager; 
        private LiveAuthClient _authClient; 
        private LiveConnectSession _liveSession; 
 
        /// <summary> 
        /// Defines the scopes the application needs. 
        /// </summary> 
        private static readonly string[] Scopes = { "wl.signin", "wl.basic", "wl.offline_access" }; 
         
        /// <summary> 
        /// Initializes a new instance of the <see cref="MicrosoftService"/> class. 
        /// </summary> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public MicrosoftService(ILogManager logManager) 
        { 
            _logManager = logManager; 
        } 
 
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception = null; 
            try 
            { 
                _authClient = new LiveAuthClient(Constants.MicrosoftClientId); 
                var loginResult = await _authClient.InitializeAsync(Scopes); 
                var result = await _authClient.LoginAsync(Scopes); 
                if (result.Status == LiveConnectSessionStatus.Connected) 
                { 
                    _liveSession = loginResult.Session; 
                    var session = new Session 
                    { 
                        AccessToken = result.Session.AccessToken, 
                        ExpireDate = result.Session.Expires.DateTime, 
                        Provider = Constants.MicrosoftProvider, 
                    }; 
 
                    return session; 
                } 
            } 
            catch (LiveAuthException ex) 
            { 
                throw new InvalidOperationException("Login canceled.", ex); 
            } 
            catch (Exception e) 
            { 
                exception = e; 
            } 
 
            await _logManager.LogAsync(exception); 
            return null; 
        } 
 
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            if (_authClient == null) 
            { 
                _authClient = new LiveAuthClient(Constants.MicrosoftClientId); 
                var loginResult = await _authClient.InitializeAsync(Scopes); 
            } 
 
            _authClient.Logout(); 
        } 
    }

 SessionService 是

/// <summary> 
    /// The service session. 
    /// </summary> 
    public class SessionService : ISessionService 
    { 
        private readonly IApplicationSettingsService _applicationSettings; 
        private readonly IFacebookService _facebookService; 
        private readonly IMicrosoftService _microsoftService; 
        private readonly IGoogleService _googleService; 
        private readonly ILogManager _logManager; 
         
        /// <summary> 
        /// Initializes a new instance of the <see cref="SessionService" /> class. 
        /// </summary> 
        /// <param name="applicationSettings">The application settings.</param> 
        /// <param name="facebookService">The facebook service.</param> 
        /// <param name="microsoftService">The microsoft service.</param> 
        /// <param name="googleService">The google service.</param> 
        /// <param name="logManager">The log manager.</param> 
        public SessionService(IApplicationSettingsService applicationSettings, 
            IFacebookService facebookService, 
            IMicrosoftService microsoftService, 
            IGoogleService googleService, ILogManager logManager) 
        { 
            _applicationSettings = applicationSettings; 
            _facebookService = facebookService; 
            _microsoftService = microsoftService; 
            _googleService = googleService; 
            _logManager = logManager; 
        } 
 
        /// <summary> 
        /// Gets the session. 
        /// </summary> 
        /// <returns>The session object.</returns> 
        public Session GetSession() 
        { 
            var expiryValue = DateTime.MinValue; 
            string expiryTicks = LoadEncryptedSettingValue("session_expiredate"); 
            if (!string.IsNullOrWhiteSpace(expiryTicks)) 
            { 
                long expiryTicksValue; 
                if (long.TryParse(expiryTicks, out expiryTicksValue)) 
                { 
                    expiryValue = new DateTime(expiryTicksValue); 
                } 
            } 
 
            var session = new Session 
            { 
                AccessToken = LoadEncryptedSettingValue("session_token"), 
                Id = LoadEncryptedSettingValue("session_id"), 
                ExpireDate = expiryValue, 
                Provider = LoadEncryptedSettingValue("session_provider") 
            }; 
 
            _applicationSettings.Set(Constants.LoginToken, true); 
            _applicationSettings.Save(); 
            return session; 
        } 
 
        /// <summary> 
        /// The save session. 
        /// </summary> 
        /// <param name="session"> 
        /// The session. 
        /// </param> 
        private void Save(Session session) 
        { 
            SaveEncryptedSettingValue("session_token", session.AccessToken); 
            SaveEncryptedSettingValue("session_id", session.Id); 
            SaveEncryptedSettingValue("session_expiredate", session.ExpireDate.Ticks.ToString(CultureInfo.InvariantCulture)); 
            SaveEncryptedSettingValue("session_provider", session.Provider); 
            _applicationSettings.Set(Constants.LoginToken, true); 
            _applicationSettings.Save(); 
        } 
 
        /// <summary> 
        /// The clean session. 
        /// </summary> 
        private void CleanSession() 
        { 
            _applicationSettings.Reset("session_token"); 
            _applicationSettings.Reset("session_id"); 
            _applicationSettings.Reset("session_expiredate"); 
            _applicationSettings.Reset("session_provider"); 
            _applicationSettings.Reset(Constants.LoginToken); 
            _applicationSettings.Save(); 
        } 
 
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <param name="provider"> 
        /// The provider. 
        /// </param> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<bool> LoginAsync(string provider) 
        { 
            Exception exception = null; 
            try 
            { 
                Session session = null; 
                switch (provider) 
                { 
                    case Constants.FacebookProvider: 
                        session = await _facebookService.LoginAsync(); 
                        break; 
                    case Constants.MicrosoftProvider: 
                        session = await _microsoftService.LoginAsync(); 
                        break; 
                    case Constants.GoogleProvider: 
                        session = await _googleService.LoginAsync(); 
                        break; 
                } 
                if (session != null) 
                { 
                    Save(session); 
                } 
 
                return true; 
            } 
            catch (InvalidOperationException e) 
            { 
                throw; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
 
            return false; 
        } 
 
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            Exception exception = null; 
            try 
            { 
                var session = GetSession(); 
                switch (session.Provider) 
                { 
                    case Constants.FacebookProvider: 
                        _facebookService.Logout(); 
                        break; 
                    case Constants.MicrosoftProvider: 
                        _microsoftService.Logout(); 
                        break; 
                    case Constants.GoogleProvider: 
                        _googleService.Logout(); 
                        break; 
                } 
                CleanSession(); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
 
        /// <summary> 
        /// Loads an encrypted setting value for a given key. 
        /// </summary> 
        /// <param name="key"> 
        /// The key to load. 
        /// </param> 
        /// <returns> 
        /// The value of the key. 
        /// </returns> 
        private string LoadEncryptedSettingValue(string key) 
        { 
            string value = null; 
 
            var protectedBytes = _applicationSettings.Get<byte[]>(key); 
            if (protectedBytes != null) 
            { 
                byte[] valueBytes = ProtectedData.Unprotect(protectedBytes, null); 
                value = Encoding.UTF8.GetString(valueBytes, 0, valueBytes.Length); 
            } 
 
            return value; 
        } 
 
        /// <summary> 
        /// Saves a setting value against a given key, encrypted. 
        /// </summary> 
        /// <param name="key"> 
        /// The key to save against. 
        /// </param> 
        /// <param name="value"> 
        /// The value to save against. 
        /// </param> 
        /// <exception cref="System.ArgumentOutOfRangeException"> 
        /// The key or value provided is unexpected. 
        /// </exception> 
        private void SaveEncryptedSettingValue(string key, string value) 
        { 
            if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value)) 
            { 
                byte[] valueBytes = Encoding.UTF8.GetBytes(value); 
 
                // Encrypt the value by using the Protect() method. 
                byte[] protectedBytes = ProtectedData.Protect(valueBytes, null); 
                _applicationSettings.Set(key, protectedBytes); 
                _applicationSettings.Save(); 
            } 
        } 
    }

现在是时候构建用户界面了,由于我使用的是 MVVM,所以我创建了一个 LoginViewModel 来绑定到 LoginView。

LoginViewModel 是

 /// <summary> 
    /// The login view model. 
    /// </summary> 
    public class LoginViewModel : ViewModelBase 
    { 
        private readonly ILogManager _logManager; 
        private readonly IMessageBoxService _messageBox; 
        private readonly INavigationService _navigationService; 
        private readonly ISessionService _sessionService; 
        private bool _inProgress; 
 
        /// <summary> 
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class. 
        /// </summary> 
        /// <param name="navigationService"> 
        /// The navigation service. 
        /// </param> 
        /// <param name="sessionService"> 
        /// The session service. 
        /// </param> 
        /// <param name="messageBox"> 
        /// The message box. 
        /// </param> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public LoginViewModel(INavigationService navigationService, 
            ISessionService sessionService, 
            IMessageBoxService messageBox, 
            ILogManager logManager) 
        { 
            _navigationService = navigationService; 
            _sessionService = sessionService; 
            _messageBox = messageBox; 
            _logManager = logManager; 
            LoginCommand = new RelayCommand<string>(LoginAction); 
        } 
 
        /// <summary> 
        /// Gets or sets a value indicating whether in progress. 
        /// </summary> 
        /// <value> 
        /// The in progress. 
        /// </value> 
        public bool InProgress 
        { 
            get { return _inProgress; } 
            set { Set(() => InProgress, ref _inProgress, value); } 
        } 
 
        /// <summary> 
        /// Gets the facebook login command. 
        /// </summary> 
        /// <value> 
        /// The facebook login command. 
        /// </value> 
        public ICommand LoginCommand { get; private set; } 
 
        /// <summary> 
        /// Facebook's login action. 
        /// </summary> 
        /// <param name="provider"> 
        /// The provider. 
        /// </param> 
        private async void LoginAction(string provider) 
        { 
            Exception exception = null; 
            bool isToShowMessage = false; 
            try 
            { 
                InProgress = true; 
                var auth = await _sessionService.LoginAsync(provider); 
                if (!auth) 
                { 
                    await _messageBox.ShowAsync(AppResources.LoginView_LoginNotAllowed_Message, 
                        AppResources.MessageBox_Title, 
                        new List<string> 
                    { 
                        AppResources.Button_OK 
                    }); 
                } 
                else 
                { 
                    _navigationService.NavigateTo(new Uri(Constants.MainView, UriKind.Relative)); 
                } 
 
                InProgress = false; 
            } 
            catch (InvalidOperationException e) 
            { 
                InProgress = false; 
                isToShowMessage = true; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (isToShowMessage) 
            { 
                await _messageBox.ShowAsync(AppResources.LoginView_AuthFail, AppResources.ApplicationTitle, new List<string> { AppResources.Button_OK }); 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
    }

注意:在 LoginAction 中,参数 provider 是 LoginCommand 收到的 CommandParameter 的值,这在登录页面设置。

LoginPage.xaml 是

<phone:PhoneApplicationPage x:Class="AuthenticationSample.WP80.Views.LoginView" 
                            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                            xmlns:Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8" 
                            xmlns:controls="clr-namespace:Facebook.Client.Controls;assembly=Facebook.Client" 
                            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
                            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                            xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
                            xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
                            xmlns:converters="clr-namespace:Cimbalino.Phone.Toolkit.Converters;assembly=Cimbalino.Phone.Toolkit" 
                            Orientation="Portrait" 
                            SupportedOrientations="Portrait" 
                            shell:SystemTray.IsVisible="True" 
                            mc:Ignorable="d"> 
    <phone:PhoneApplicationPage.DataContext> 
        <Binding Mode="OneWay" 
                 Path="LoginViewModel" 
                 Source="{StaticResource Locator}" /> 
    </phone:PhoneApplicationPage.DataContext> 
    <phone:PhoneApplicationPage.Resources> 
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> 
    </phone:PhoneApplicationPage.Resources> 
    <phone:PhoneApplicationPage.FontFamily> 
        <StaticResource ResourceKey="PhoneFontFamilyNormal" /> 
    </phone:PhoneApplicationPage.FontFamily> 
    <phone:PhoneApplicationPage.FontSize> 
        <StaticResource ResourceKey="PhoneFontSizeNormal" /> 
    </phone:PhoneApplicationPage.FontSize> 
    <phone:PhoneApplicationPage.Foreground> 
        <StaticResource ResourceKey="PhoneForegroundBrush" /> 
    </phone:PhoneApplicationPage.Foreground> 
    <!--  LayoutRoot is the root grid where all page content is placed  --> 
    <Grid x:Name="LayoutRoot" Background="Transparent"> 
        <Grid.RowDefinitions> 
            <RowDefinition Height="Auto" /> 
            <RowDefinition Height="*" /> 
        </Grid.RowDefinitions> 
 
        <!--  TitlePanel contains the name of the application and page title  --> 
        <StackPanel x:Name="TitlePanel" 
                    Grid.Row="0" 
                    Margin="12,17,0,28"> 
            <TextBlock Margin="12,0" 
                       Style="{StaticResource PhoneTextNormalStyle}" 
                       Text="{Binding LocalizedResources.ApplicationTitle, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
            <TextBlock Margin="9,-7,0,0" 
                       Style="{StaticResource PhoneTextTitle1Style}" 
                       Text="{Binding LocalizedResources.LoginView_Title, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
        </StackPanel> 
 
        <!--  ContentPanel - place additional content here  --> 
        <Grid x:Name="ContentPanel" 
              Grid.Row="1" 
              Margin="24,0,0,-40"> 
            <Grid.RowDefinitions> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock Grid.Row="0" 
                       Style="{StaticResource PhoneTextTitle2Style}" 
                       Text="{Binding LocalizedResources.LoginView_UserAccount, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
            <Button Grid.Row="1" 
                    Margin="10" 
                    Command="{Binding LoginCommand}" 
                    CommandParameter="facebook" 
                    Content="Facebook" /> 
            <Button Grid.Row="2" 
                    Margin="10" 
                    Command="{Binding LoginCommand}" 
                    CommandParameter="microsoft" 
                    Content="Microsoft" /> 
            <Button Grid.Row="3" 
                    Margin="10" 
                    Command="{Binding LoginCommand}" 
                    CommandParameter="google" 
                    Content="Google" /> 
       </Grid> 
        <Grid Visibility="{Binding InProgress, Converter={StaticResource BooleanToVisibilityConverter}}" 
            Grid.Row="0" 
                   Grid.RowSpan="2"> 
            <Rectangle  
                   Fill="Black" 
                   Opacity="0.75" /> 
            <TextBlock  
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Center" 
                   Text="{Binding LocalizedResources.LoginView_AuthMessage, 
                                  Mode=OneWay, 
                                  Source={StaticResource LocalizedStrings}}" /> 
            <ProgressBar IsIndeterminate="True" IsEnabled="True" Margin="0,60,0,0"/> 
        </Grid> 
     
    </Grid> 
</phone:PhoneApplicationPage>

登录用户界面

源代码文件

  • IFacebookService FacebookService 的接口
  • IGoogleService GoogleService 的接口
  • ILogManager LogManager 的接口
  • IMicrosoftService MicrosoftService 的接口
  • ISessionProvider 所有提供商接口的接口(通用方法)
  • ISessionService SessionService 的接口
  • Session 类用于保存有关会话的信息(提供商、令牌、过期日期)
  • FacebookService 类,包含使用 Facebook 提供商登录/注销的所有逻辑
  • GoogleService 类,包含使用 Google 提供商登录/注销的所有逻辑
  • MicrosoftService 类,包含使用 Microsoft 提供商登录/注销的所有逻辑
  • SessionService 类,用于管理登录/注销(它将使用前面描述的所有提供商服务)
  • LoginViewModel 类,用于绑定到 LoginView.xaml
  • LoginView 类,代表登录页面
  • MainViewModel 类,用于绑定到 MainView.xaml
  • MainView 类,在登录成功后显示
  • AboutViewModel 类,用于绑定到 AboutView.xaml
  • AboutView 类,代表关于页面
  • ViewModelLocator 类包含对应用程序中所有视图模型的静态引用,并提供绑定的入口点。

构建示例

  1. 启动 Visual Studio Express 2012 for Windows 8,然后选择 **文件** > **打开** > **项目/解决方案**。
  2. 转到您解压缩示例的目录。进入以示例命名的目录,然后双击 Visual Studio Express 2012 for Windows 8 Solution (.sln) 文件。
  3. 按 F7 或使用 **生成** > **生成解决方案** 来构建示例。

 注意:您可以在 Windows 8.1 中使用 Visual Studio 2013。

 运行示例

要调试并运行应用程序,请按 F5 或使用 **调试** > **开始调试**。要在不调试的情况下运行应用程序,请按 Ctrl+F5 或使用 **调试** > **不调试运行**。

相关示例

更多信息

在 Twitter 上提问 @saramgsilva

© . All rights reserved.