向 Xamarin Forms 应用添加身份验证

概述

本主题演示如何从客户端应用程序对应用服务移动应用的用户进行身份验证。 在本教程中,使用应用服务支持的标识提供者向 Xamarin Forms 快速入门项目添加身份验证。 移动应用成功进行身份验证和授权后,将显示用户 ID 值,该用户能够访问受限制的表数据。

先决条件

为了使本教程达到最佳效果,建议先完成创建 Xamarin Forms 应用教程。 完成此教程后,用户可以获得一个 Xamarin Forms 项目,它是一个多平台 TodoList 应用。

如果不使用下载的快速入门服务器项目,必须将身份验证扩展包添加到项目。 有关服务器扩展包的详细信息,请参阅使用适用于 Azure 移动应用的 .NET 后端服务器 SDK

注册应用以进行身份验证并配置应用服务

首先,需要在标识提供者站点上注册应用,然后在移动应用后端设置提供者生成的凭据。

  1. 请按照以下提供者特定的说明来配置首选标识提供者:

  2. 为要在应用中支持的各提供者重复上述步骤。

将应用添加到允许的外部重定向 URL

安全身份验证要求为应用定义新的 URL 方案。 此方案允许在完成身份验证过程后,身份验证系统重定向到应用。 在本教程中,我们自始至终使用 URL 方案 appname 。 但是,可以使用任何你所选的 URL 方案。 对于移动应用程序而言,它应是唯一的。 在服务器端启用重定向:

  1. Azure 门户中,选择应用服务。

  2. 单击“身份验证/授权”菜单选项。

  3. 在“允许的外部重定向 URL”中,输入 url_scheme_of_your_app://easyauth.callback。 此字符串中的 url_scheme_of_your_app 是移动应用程序的 URL 方案。 它应该遵循协议的正常 URL 规范(仅使用字母和数字,并以字母开头)。 应记下此字符串,因为在一些地方需要使用此 URL 方案调整移动应用代码。

  4. 单击 “确定”

  5. 单击“保存” 。

将权限限制给已经过身份验证的用户

默认情况下,可匿名调用移动应用后端中的 API。 接下来,需限制为仅可访问已验证的客户端。

  • Node.js 后端(通过 Azure 门户)

    在移动应用设置中,单击“简易表”并选择相应的表。 单击“更改权限”,为所有权限选择“仅限已验证的访问”,并单击“保存”。

  • .NET 后端 (C#):

    在服务器项目中,导航到“控制器” > “TodoItemController.cs”。 将 [Authorize] 属性添加到“TodoItemController”类,如下所示。 若要限制为仅可访问特定方法,还可只向这些方法应用此属性(而非类)。 重新发布服务器项目。

    [Authorize]
    public class TodoItemController : TableController<TodoItem>
    
  • Node.js 后端(通过 Node.js 代码)

    若要访问表时需验证身份,请向 Node.js 服务器脚本添加以下行:

    table.access = 'authenticated';
    

    有关更多详细信息,请参阅如何:要求在访问表时进行身份验证。 若要了解如何从网站下载快速入门代码项目,请参阅如何:使用 Git 下载 Node.js 后端快速入门代码项目

向可移植类库添加身份验证

移动应用使用 MobileServiceClient 上的 LoginAsync 扩展方法通过应用服务身份验证登录用户。 此示例使用服务器托管的身份验证流,在应用中显示提供程序的登录界面。 有关详细信息,请参阅服务器托管的身份验证。 若要在生产应用中提供更好的用户体验,则应考虑改用客户端托管的身份验证

若要使用 Xamarin Forms 项目进行身份验证,请在可移植类库中为应用定义 IAuthenticate 接口。 然后,将“登录”按钮添加到可移植类库中定义的用户界面,用户单击此按钮即可开始进行身份验证。 身份验证成功后,将从移动应用后端加载数据。

为应用支持的每个平台实现 IAuthenticate 接口。

  1. 在 Visual Studio 或 Xamarin Studio 中,从名称中包含 Portable 的项目(该项目是可移植类库项目)中打开 App.cs,然后添加以下 using 语句:

    using System.Threading.Tasks;
    
  2. 在 App.cs 中,在 App 类定义前添加以下 IAuthenticate 接口定义。

    public interface IAuthenticate
    {
        Task<bool> Authenticate();
    }
    
  3. 若要使用平台特定的实现初始化接口,可向 App 类添加以下静态成员。

    public static IAuthenticate Authenticator { get; private set; }
    
    public static void Init(IAuthenticate authenticator)
    {
        Authenticator = authenticator;
    }
    
  4. 从可移植类库项目中打开 TodoList.xaml,在 buttonsPanel 布局元素中现有按钮之后添加以下 Button 元素:

      <Button x:Name="loginButton" Text="Sign-in" MinimumHeightRequest="30" 
        Clicked="loginButton_Clicked"/>
    

    此按钮通过移动应用后端触发服务器托管的身份验证。

  5. 从可移植类库项目中打开 TodoList.xaml.cs,并将以下字段添加到 TodoList 类:

    // Track whether the user has authenticated. 
    bool authenticated = false;
    
  6. OnAppearing 方法替换为以下代码:

    protected override async void OnAppearing()
    {
        base.OnAppearing();
    
        // Refresh items only when authenticated.
        if (authenticated == true)
        {
            // Set syncItems to true in order to synchronize the data 
            // on startup when running in offline mode.
            await RefreshItems(true, syncItems: false);
    
            // Hide the Sign-in button.
            this.loginButton.IsVisible = false;
        }
    }
    

    该代码可确保仅在用户经过身份验证后,才从服务刷新数据。

  7. 在 TodoList 类中为 Clicked 事件添加以下处理程序:

    async void loginButton_Clicked(object sender, EventArgs e)
    {
        if (App.Authenticator != null)
            authenticated = await App.Authenticator.Authenticate();
    
        // Set syncItems to true to synchronize the data on startup when offline is enabled.
        if (authenticated == true)
            await RefreshItems(true, syncItems: false);
    }
    
  8. 保存更改,重新生成可移植类库项目,并验证没有错误。

向 Android 应用添加身份验证

本部分演示如何在 Android 应用项目中实现 IAuthenticate 接口。如果不要支持 Android 设备,请跳过本部分。

  1. 在 Visual Studio 或 Xamarin Studio 中,右键单击 droid 项目,然后单击“设为启动项目”。
  2. 按 F5 在调试器中启动项目,然后验证启动该应用后,是否会引发状态代码为 401(“未授权”)的未处理异常。 因为后端上的访问仅限于授权用户,因此会生成 401 代码。
  3. 在 Android 项目中打开 MainActivity.cs,并添加以下 using 语句:

    using Microsoft.WindowsAzure.MobileServices;
    using System.Threading.Tasks;
    
  4. 更新 MainActivity 类,实现 IAuthenticate 接口,如下所示:

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity, IAuthenticate
    
  5. 通过添加 MobileServiceUser 字段和 IAuthenticate 接口所需的 Authenticate 方法,更新 MainActivity 类,如下所示:

    // Define a authenticated user.
    private MobileServiceUser user;
    
    public async Task<bool> Authenticate()
    {
        var success = false;
        var message = string.Empty;
        try
        {
            // Sign in with MicrosoftAccount login using a server-managed flow.
            user = await TodoItemManager.DefaultManager.CurrentClient.LoginAsync(this,
                    MobileServiceAuthenticationProvider.MicrosoftAccount, "{url_scheme_of_your_app}");
            if (user != null)
            {
                message = string.Format("you are now signed-in as {0}.",
                    user.UserId);
                success = true;
            }
        }
        catch (Exception ex)
        {
            message = ex.Message;
        }
    
        // Display the success or failure message.
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.SetMessage(message);
        builder.SetTitle("Sign-in result");
        builder.Create().Show();
    
        return success;
    }
    

    如果使用的是 MicrosoftAccount 以外的其他标识提供者,请为 [MobileServiceAuthenticationProvider] 选择不同的值。

  6. <application> 元素内添加以下 XML,更新 AndroidManifest.xml 文件:

    <activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity" android:launchMode="singleTop" android:noHistory="true">
      <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="{url_scheme_of_your_app}" android:host="easyauth.callback" />
      </intent-filter>
    </activity>
    

    {url_scheme_of_your_app} 替换为 URL 方案。

  7. 调用 LoadApplication() 之前,向 MainActivity 类的 OnCreate 方法添加以下代码:

    // Initialize the authenticator before loading the app.
    App.Init((IAuthenticate)this);
    

    该代码可确保验证器在应用加载前进行初始化。

  8. 重新生成应用,运行它,然后使用所选的身份验证提供者登录,并验证是否能够以经过身份验证的用户身份访问数据。

向 iOS 应用添加身份验证

本部分演示如何在 iOS 应用项目中实现 IAuthenticate 接口。如果不要支持 iOS 设备,请跳过本部分。

  1. 在 Visual Studio 或 Xamarin Studio 中,右键单击 iOS 项目,然后单击“设为启动项目”。
  2. 按 F5 在调试器中启动项目,然后验证启动该应用后,是否会引发状态代码为 401(“未授权”)的未处理异常。之所以会生成 401 响应,是因为对后端的访问仅限于授权用户。
  3. 打开 iOS 项目中的 AppDelegate.cs,并添加以下 using 语句:

    using Microsoft.WindowsAzure.MobileServices;
    using System.Threading.Tasks;
    
  4. 更新 AppDelegate 类,以实现 IAuthenticate 接口,如下所示:

    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IAuthenticate
    
  5. 通过添加 MobileServiceUser 字段和 IAuthenticate 接口所需的 Authenticate 方法,更新 AppDelegate 类,如下所示:

    // Define a authenticated user.
    private MobileServiceUser user;
    
    public async Task<bool> Authenticate()
    {
        var success = false;
        var message = string.Empty;
        try
        {
            // Sign in with MicrosoftAccount login using a server-managed flow.
            if (user == null)
            {
                user = await TodoItemManager.DefaultManager.CurrentClient
                    .LoginAsync(UIApplication.SharedApplication.KeyWindow.RootViewController,
                        MobileServiceAuthenticationProvider.MicrosoftAccount, "{url_scheme_of_your_app}");
                if (user != null)
                {
                    message = string.Format("You are now signed-in as {0}.", user.UserId);
                    success = true;                        
                }
            }        
        }
        catch (Exception ex)
        {
           message = ex.Message;
        }
    
        // Display the success or failure message.
        UIAlertView avAlert = new UIAlertView("Sign-in result", message, null, "OK", null);
        avAlert.Show();         
    
        return success;
    }
    

    如果使用的是 MicrosoftAccount 以外的其他标识提供者,请为 [MobileServiceAuthenticationProvider] 选择其他值。

  6. 通过添加 OpenUrl 方法重载更新 AppDelegate 类,如下所示:

    public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
    {
        return TodoItemManager.DefaultManager.CurrentClient.ResumeWithURL(url);
    }
    
  7. 调用 LoadApplication() 之前,向 FinishedLaunching 方法添加以下代码行:

    App.Init(this);
    

    该代码可确保验证器在应用加载前进行初始化。

  8. 打开 Info.plist 并添加 URL 类型。 将“标识符”设置为所选的名称,将“URL 方案”设置为应用的 URL 方案,将“角色”设置为“无”。

  9. 重新生成应用,运行它,然后使用所选的身份验证提供者登录,并验证是否能够以经过身份验证的用户身份访问数据。

向 Windows 10(包括 Phone)应用项目添加身份验证

本部分演示如何在 Windows 10 应用项目中实现 IAuthenticate 接口。 相同的步骤适用于通用 Windows 平台 (UWP) 项目,但使用的是 UWP 项目(具有已注明的更改)。 如果不要支持 Windows 设备,请跳过本部分。

  1. 在 Visual Studio 中,右键单击 UWP 项目,然后单击“设为启动项目”。
  2. 按 F5 在调试器中启动项目,然后验证启动该应用后,是否会引发状态代码为 401(“未授权”)的未处理异常。之所以会发生此 401 响应,是因为对后端的访问仅限于授权用户。
  3. 打开 Windows 应用项目的 MainPage.xaml.cs,并添加以下 using 语句:

    using Microsoft.WindowsAzure.MobileServices;
    using System.Threading.Tasks;
    using Windows.UI.Popups;
    using <your_Portable_Class_Library_namespace>;
    

    <your_Portable_Class_Library_namespace> 替换为可移植类库的命名空间。

  4. 更新 MainPage 类,实现 IAuthenticate 接口,如下所示:

    public sealed partial class MainPage : IAuthenticate
    
  5. 通过添加 MobileServiceUser 字段和 IAuthenticate 接口所需的 Authenticate 方法,更新 MainPage 类,如下所示:

    // Define a authenticated user.
    private MobileServiceUser user;
    
    public async Task<bool> Authenticate()
    {
        string message = string.Empty;
        var success = false;
    
        try
        {
            // Sign in with MicrosoftAccount login using a server-managed flow.
            if (user == null)
            {
                user = await TodoItemManager.DefaultManager.CurrentClient
                        .LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount, "{url_scheme_of_your_app}");
                if (user != null)
                {
                    success = true;
                    message = string.Format("You are now signed-in as {0}.", user.UserId);
                }
            }
    
        }
        catch (Exception ex)
        {
            message = string.Format("Authentication Failed: {0}", ex.Message);
        }
    
        // Display the success or failure message.
        await new MessageDialog(message, "Sign-in result").ShowAsync();
    
        return success;
    }
    

    如果使用的是 MicrosoftAccount 以外的其他标识提供者,请为 [MobileServiceAuthenticationProvider] 选择其他值。

  6. 调用 LoadApplication() 之前,在 MainPage 类的构造函数中添加以下代码行:

    // Initialize the authenticator before loading the app.
    <your_Portable_Class_Library_namespace>.App.Init(this);
    

    <your_Portable_Class_Library_namespace> 替换为可移植类库的命名空间。

  7. 如果使用的是 UWP,则将以下 OnActivated 方法重写添加到 App 类:

    ```
    protected override void OnActivated(IActivatedEventArgs args)
    {
        base.OnActivated(args);
    
         if (args.Kind == ActivationKind.Protocol)
         {
             ProtocolActivatedEventArgs protocolArgs = args as ProtocolActivatedEventArgs;
             TodoItemManager.DefaultManager.CurrentClient.ResumeWithURL(protocolArgs.Uri);
         }
    
    }
    ```
    
  8. 打开 Package.appxmanifest,添加 Protocol 声明。 将“显示名称”设置为所选的名称,将“名称”设置为应用的 URL 方案。

  9. 重新生成应用,运行它,然后使用所选的身份验证提供者登录,并验证是否能够以经过身份验证的用户身份访问数据。

    后续步骤

完成此基本身份验证教程后,请考虑继续学习以下教程之一:

  • 为应用启用脱机同步
    了解如何使用移动应用后端向应用添加脱机支持。脱机同步允许最终用户与移动应用交互(查看、添加或修改数据),即使在没有网络连接时也是如此。