Добавление проверки подлинности в приложение Windows

Обзор

В этом разделе показано, как добавить проверку подлинности на основе облака в мобильное приложение. В этом учебнике вы добавите проверку подлинности в проект быстрого запуска универсальной платформы Windows (UWP) для мобильных приложений, используя поставщик удостоверений, поддерживаемый службой приложений Azure. После успешной проверки подлинности и авторизации сервером мобильных приложений отображается значение идентификатора пользователя.

Этот учебник создан на основе краткого руководства по мобильным приложениям. Вам необходимо сначала изучить учебник Начало работы с мобильными приложениями.

Регистрация приложения для проверки подлинности и настройка службы приложений

Сначала необходимо зарегистрировать приложение на сайте поставщика удостоверений, а затем ввести созданные поставщиком учетные данные в серверной части мобильного приложения.

  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. Выберите команду Сохранить.

Ограничение разрешений для пользователей, прошедших проверку подлинности

По умолчанию API-интерфейсы в серверной части мобильных приложений могут вызываться анонимно. Далее необходимо ограничить доступ всем клиентам, не прошедшим проверку подлинности.

  • Серверная часть Node.js (через портал Azure):

    В параметрах мобильных приложений щелкните простые таблицы и выберите таблицу. Щелкните Изменить разрешения, выберите для всех разрешений параметр Authenticated access only (Доступ только с проверкой подлинности) и нажмите кнопку Сохранить.

  • Серверная часть .NET (C#):

    В серверном проекте перейдите к контроллерам>TodoItemController. CS. Примените атрибут [Authorize] к классу TodoItemController следующим образом. Чтобы предоставить доступ только определенным методам, этот атрибут можно также применить именно к ним, а не к классу. Повторная публикация серверного проекта

      [Authorize]
      public class TodoItemController : TableController<TodoItem>
    
  • Серверная служба Node.js (через код Node.js) :

    Чтобы доступ к таблице предоставлялся только после проверки подлинности, добавьте в серверный скрипт Node.js следующую строку:

      table.access = 'authenticated';
    

    Дополнительные сведения см. в разделе Практическое руководство. Обязательная аутентификация для доступа к таблицам. Узнайте, как загрузить проект быстрого запуска кода с веб-узла, в разделе Загрузка серверной части на основе Node.js в виде готового кода для быстрого запуска с помощью Git.

Теперь можно убедиться, что анонимный доступ к серверной части был отключен. Назначив проект приложения UWP запускаемым проектом, разверните и запустите приложение. Убедитесь в том, что после его запуска порождается необработанное исключение с кодом состояния 401 (не авторизован). Это происходит потому, что приложение пытается получить доступ к коду мобильного приложения от имени пользователя, не прошедшего проверку подлинности, но таблице TodoItem теперь требуется проверка подлинности.

Далее вы обновите приложение, чтобы оно выполняло проверку подлинности пользователей перед запросом ресурсов из службы приложений.

Добавление проверки подлинности в приложение

  1. В файле MainPage.xaml.cs проекта приложения UWP добавьте следующий фрагмент кода:

     // Define a member variable for storing the signed-in user. 
     private MobileServiceUser user;
    
     // Define a method that performs the authentication process
     // using a Facebook sign-in. 
     private async System.Threading.Tasks.Task<bool> AuthenticateAsync()
     {
         string message;
         bool success = false;
         try
         {
             // Change 'MobileService' to the name of your MobileServiceClient instance.
             // Sign-in using Facebook authentication.
             user = await App.MobileService
                 .LoginAsync(MobileServiceAuthenticationProvider.Facebook, "{url_scheme_of_your_app}");
             message =
                 string.Format("You are now signed in - {0}", user.UserId);
    
             success = true;
         }
         catch (InvalidOperationException)
         {
             message = "You must log in. Login Required";
         }
    
         var dialog = new MessageDialog(message);
         dialog.Commands.Add(new UICommand("OK"));
         await dialog.ShowAsync();
         return success;
     }
    

    Этот код выполняет проверку подлинности пользователя с помощью имени входа в Facebook. Если используется поставщик удостоверений, отличный от Facebook, измените значение MobileServiceAuthenticationProvider выше на значение для вашего поставщика.

  2. Замените метод OnNavigatedTo() в файле MainPage.xaml.cs. Затем добавьте кнопку Вход в приложение, которое запускает проверку подлинности.

     protected override async void OnNavigatedTo(NavigationEventArgs e)
     {
         if (e.Parameter is Uri)
         {
             App.MobileService.ResumeWithURL(e.Parameter as Uri);
         }
     }
    
  3. Добавьте в файл MainPage.xaml.cs следующий фрагмент кода:

     private async void ButtonLogin_Click(object sender, RoutedEventArgs e)
     {
         // Login the user and then load data from the mobile app.
         if (await AuthenticateAsync())
         {
             // Switch the buttons and load items from the mobile app.
             ButtonLogin.Visibility = Visibility.Collapsed;
             ButtonSave.Visibility = Visibility.Visible;
             //await InitLocalStoreAsync(); //offline sync support.
             await RefreshTodoItems();
         }
     }
    
  4. Откройте файл проекта MainPage.xaml, найдите элемент, который определяет кнопку Сохранить и замените его следующим кодом:

     <Button Name="ButtonSave" Visibility="Collapsed" Margin="0,8,8,0" 
             Click="ButtonSave_Click">
         <StackPanel Orientation="Horizontal">
             <SymbolIcon Symbol="Add"/>
             <TextBlock Margin="5">Save</TextBlock>
         </StackPanel>
     </Button>
     <Button Name="ButtonLogin" Visibility="Visible" Margin="0,8,8,0" 
             Click="ButtonLogin_Click" TabIndex="0">
         <StackPanel Orientation="Horizontal">
             <SymbolIcon Symbol="Permissions"/>
             <TextBlock Margin="5">Sign in</TextBlock> 
         </StackPanel>
     </Button>
    
  5. Добавьте в файл App.xaml.cs следующий фрагмент кода:

     protected override void OnActivated(IActivatedEventArgs args)
     {
         if (args.Kind == ActivationKind.Protocol)
         {
             ProtocolActivatedEventArgs protocolArgs = args as ProtocolActivatedEventArgs;
             Frame content = Window.Current.Content as Frame;
             if (content.Content.GetType() == typeof(MainPage))
             {
                 content.Navigate(typeof(MainPage), protocolArgs.Uri);
             }
         }
         Window.Current.Activate();
         base.OnActivated(args);
     }
    
  6. Откройте файл Package.appxmanifest, перейдите к разделу Объявления, в раскрывающемся списке Доступные объявления выберите пункт Протокол и нажмите кнопку Добавить. Далее настройте свойства объявления протокола. В поле Отображаемое имя добавьте имя, которое должно отображаться для пользователей приложения. В поле Имя добавьте {url_scheme_of_your_app}.

  7. Нажмите клавишу F5, чтобы запустить приложение, нажмите кнопку Вход и войдите в приложение с помощью выбранного поставщика удостоверений. После успешного входа приложение работает без ошибок, а вы должны быть в состоянии выполнять запросы к серверной части и обновлять данные.

Сохранение токена проверки подлинности в клиенте

В предыдущем примере был показан стандартный вход, при котором клиенту нужно подключаться к поставщику удостоверений и службе приложений каждый раз, когда приложение запускается. Мало того что этот метод неэффективен, вы можете столкнуться с проблемами, связанными с использованием приложения, если большое количество клиентов попытаются запустить приложение одновременно. Лучше кэшировать токен авторизации, который возвратила служба приложений, причем делать это до входа через поставщика.

Примечание

Токен, выданный службами приложений, можно кэшировать независимо от используемой аутентификации (управляемая службой либо клиентом). Этот учебник использует управляемую сервером проверку подлинности.

  1. В файле проекта MainPage.xaml.cs добавьте следующие операторы using :

     using System.Linq;        
     using Windows.Security.Credentials;
    
  2. Замените метод AuthenticateAsync следующим кодом:

     private async System.Threading.Tasks.Task<bool> AuthenticateAsync()
     {
         string message;
         bool success = false;
    
         // This sample uses the Facebook provider.
         var provider = MobileServiceAuthenticationProvider.Facebook;
    
         // Use the PasswordVault to securely store and access credentials.
         PasswordVault vault = new PasswordVault();
         PasswordCredential credential = null;
    
         try
         {
             // Try to get an existing credential from the vault.
             credential = vault.FindAllByResource(provider.ToString()).FirstOrDefault();
         }
         catch (Exception)
         {
             // When there is no matching resource an error occurs, which we ignore.
         }
    
         if (credential != null)
         {
             // Create a user from the stored credentials.
             user = new MobileServiceUser(credential.UserName);
             credential.RetrievePassword();
             user.MobileServiceAuthenticationToken = credential.Password;
    
             // Set the user from the stored credentials.
             App.MobileService.CurrentUser = user;
    
             // Consider adding a check to determine if the token is 
             // expired, as shown in this post: https://aka.ms/jww5vp.
    
             success = true;
             message = string.Format("Cached credentials for user - {0}", user.UserId);
         }
         else
         {
             try
             {
                 // Sign in with the identity provider.
                 user = await App.MobileService
                     .LoginAsync(provider, "{url_scheme_of_your_app}");
    
                 // Create and store the user credentials.
                 credential = new PasswordCredential(provider.ToString(),
                     user.UserId, user.MobileServiceAuthenticationToken);
                 vault.Add(credential);
    
                 success = true;
                 message = string.Format("You are now signed in - {0}", user.UserId);
             }
             catch (MobileServiceInvalidOperationException)
             {
                 message = "You must sign in. Sign-In Required";
             }
         }
    
         var dialog = new MessageDialog(message);
         dialog.Commands.Add(new UICommand("OK"));
         await dialog.ShowAsync();
    
         return success;
     }
    

    В этой версии AuthenticateAsync приложение пытается использовать для доступа к службе учетные данные, хранимые в PasswordVault. Обычная попытка входа предпринимается и при отсутствии хранимых учетных данных.

    Примечание

    Срок действия кэшированного маркера может истечь до или после проверки подлинности, в процессе использования приложения. Чтобы узнать, как определить, истек ли срок действия маркера, см. сведения в этой статье. Решение по обработке ошибок авторизации, связанных с просроченными маркерами, см. в записи Caching and handling expired tokens in Azure Mobile Services managed SDK (Кэширование и обработка просроченных маркеров в SDK под управлением мобильных служб Azure).

  3. Дважды перезапустите приложение.

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

Дальнейшие действия

Вы прошли этот учебник по обычной проверке подлинности и теперь можете перейти к одному из следующих учебников:

  • Добавление push-уведомлений в приложение
    Узнайте, как добавить поддержку push-уведомлений в мобильное приложение и настроить в его серверной части использование концентраторов уведомлений Azure для отправки push-уведомлений.
  • Включение автономной синхронизации для приложения
    Узнайте, как добавить в приложение поддержку автономной работы с помощью серверной части мобильного приложения. Автономная синхронизация позволяет конечным пользователям взаимодействовать с мобильным приложением — просмотр, добавление или изменение данных, даже если отсутствует сетевое подключение.