Программная логика приложений для Windows 8 и их взаимодействие с системой

Проверка подлинности, учетные данные и профиль пользователя

Разбить на страницы
Показывать лекцию целиком

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

Есть два основных подхода по работе с учетными данными. Первая, вы можете собирать учетные данные напрямую, с помощью интерфейса Средства выбора учетных данных, или с помощью собственного пользовательского интерфейса. В любом случае, однако, следующий вопрос заключается в том, как организовать безопасное хранение учетных данных, для чего у нас имеется API хранилища учетных данных (Credential Locker API). Хранилище позволяет приложения получать учетные данные в последующих сеансах работы, таким образом, ему не нужно каждый раз просить пользователя вводить эти учетные данные (что довольно утомительно, уверен, вы это знаете).

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

По этой причине – хорошая идея делегировать эти действия другим. например, интерфейс средства выбора файлов будет, по умолчанию, шифровать пароли прежде чем передаст их вашему приложению. Или вы можете использовать второй подход для работы с учетными данными, когда приложение проверяет подлинность пользователя с помощью другого поставщика услуг, такого, как Microsoft Live Connect, Facebook, Flickr, Yahoo, и так далее. При этом поставщик выполняет всю работу по проверке подлинности и приложению лишь нужно сохранить соответствующие маркеры или другие ключи доступа для данного сервиса. Основное преимущества интегрированной проверки подлинности подобного вида заключается в том, что приложение никогда не работает с учетными данными самостоятельно, и, таким образом, ему не нужно беспокоиться об их безопасности. (Однако, приложению следует шифровать маркеры или ключе доступа, если оно их хранит. Хранилище учетных данных можно использовать и для этой цели.)

В большинстве случаев этот процесс включает в себя агента, который называется Брокер веб-проверки подлинности (Web Authentication Broker), который, в частности, работает с протоколами OAuth/OpenID и поставщиками услуг, обычно расположенными в Веб. Microsoft Live Connect – это особый случай, так как учетная запись Microsoft, используемая с ним может, кроме того, использоваться для входа в Windows. (Проверка подлинности через Live Connect так же предоставляет приложению доступ к другим данным из сервисов Live, в том числе, к Calendar, Messenger, и SkyDrive.)

Одно из других замечательных преимуществ этого второго подхода заключается в возможности работы в режиме единого входа (single sign on, SSO). Это означает, что когда пользователь авторизовался у какого-либо OAuth-поставщика в одном приложении, ему часто не нужно осуществлять вход в другие приложения, которые исопльзуют того же поставщика (если приложение сочтет это нужным). В случае с Live Connect, приложения может никогда не понадобиться запрашивать учетные данные, если та же самая учетная запись Microsoft использована для входа в Windows или связана с входом пользователя в домен.

В этом разделе мы так же кратко рассмотрим – и это все, что нужно в данном случае – информацию профиля пользователя, доступную с помощью API WinRT, вместе с API для шифрования и дешифровки. Помимо этого, я расскажу о двух других материалах по теме. Первый, это "Защита соединений и проверка подлинности запросов" (http://msdn.microsoft.com/library/windows/apps/hh986970.aspx ). Второй – это пример "Банковское приложение Магазина Windows со строгой проверкой подлинности" ( http://code.msdn.microsoft.com/windowsapps/Metro-style-banking-app-7d963c00), которое демонстрирует пример безопасной проверки подлинности и обмена данными через Интернет. Полное описание этого примера можно найти вматериале "Банковское приложение Магазина Windows: обзор кода" (http://msdn.microsoft.com/library/windows/apps/Hh464943 ), поэтому здесь мы не будем его рассматривать.

Совет по дизайну. Существует множество руководств по дизайну для различных сценариев входа в систему, касающиеся ситуаций, когда приложению требуется вход в систему для работы, или когда вход необязателен. Эти темы, а так же рекомендации о том, где разместить интерфейс для входа в систему и управления учетной записью или профилем, обсуждаются в материале "Руководство и контрольный список для элементов управления входом" (http://msdn.microsoft.com/library/windows/apps/hh965453.aspx ).

Пользовательский интерфейс средства работы с учетными данными

Так же, как WinRT предоставляет встроенный интерфейс для выбора файлов, имеется и встроенный пользовательский интерфейс для ввода учетных данных: ).

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

(рис 8.1) Интерфейс средства выбора учетных данных выводится, как и диалоговое окно сообщения, поверх приложения

Результаты из pickAsync, переданные обработчику завершения, это объект CredentialPickerResults (http://msdn.microsoft.com/library/windows/apps/windows.security.credentials.ui.credentialpickerresults.aspx ), который имеет следующие свойства. Когда вы введете какие-нибудь учетные данные в примере, вы увидите их значения, отраженные в выходных данных примера:

  • credentialuserName Строка, которая содержит введенное имя пользователя.
  • credentialPassword Строка, которая содержит пароль (обычно зашифрованный, в зависимости от параметров протокола проверки подлиности).
  • credentialDomainName Строка, содержащая имя домена, если он введен вместе с именем прользователя, (в таком виде: <domain> \<username>).
  • credentialSaved Логическое значение, которое показывает, будет ли производиться автоматическое сохранение введенных учетных данных. Это зависит от параметра средства выбора учетных данных, как обсуждается ниже.
  • ), отображает состояние флага Сохранить учетные данные (Remember My Credentals): unselected, selected, или hidden. Скоро мы рассмотрим обработку этого значения.
  • errorCode Содержит ноль, если ошибок нет, в противном случае – код ошибки.
  • credential Значение типа IBuffer, содержащее учетные данные в виде непрозрачного массива байтов. Его вы можете сохранить, если нужно, в составе состояния приложения и позднее передать обратно средству выбора учетных данных. Как это сделать, мы скоро увидим.
  • Три сценария в примере показывают различные параметры, которые вы можете использовать для вызова средства выбора учетных данных. Для этих целей присутствует три различных варианта .:

    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(targetName, message)
    .done(function (results) {
    }
          

    Второй вариант принимает те же аргументы вместе со строкой заголовка, которая появляется вместо текста "Credential Picker Sample" на рис 8.1.

    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(targetName, message, caption)
    .done(function (results) {
    }
          

    Третий вариант принимает объект ), который имеет те же свойства:строки targetName, message, и caption , вместе со следующими:

  • previousCredential Значение типа IBuffer с непрозрачной информацией об учетных данных, которые были предоставлены при предыдущем запуске средства (смотрите CredentialPickerResults.credential выше).
  • alwaysDisplayDialog Логическое значение, указывающее на то, отображается ли диалоговое окно. Значение по умолчанию – false, но это применимо лишь в том случае, если вы заполнили свойство previousCredential (с исключением для компьютеров, подключенных к домену – смотрите таблицу ниже). Цель его использования заключается в том, чтобы показать диалоговое окно, когда сохраненные учетные данные могут быть неверными, и от пользователя ожидается предоставление новых данных.
  • ) (по умолчанию ERROR_SUCCESS) которое можно отформатировать и показать в диалоговом окне. Это значение используют, когда учетные данные сначала получены от средства их выбора, но оказалось, что эти учетные данные подходят и нужно снова запустить диалоговое окно для их ввода. Вместо того, чтобы предоставлять собственное сообщение, вы можете просто получить код ошибки и позволить системе сделать все остальное. Наиболее часто встречающиеся здесь ошибки имеют следующие коды: 1326 (ошибка входа), 1330 (истек пароль), 2202 (неправильное имя пользователя), 1907 или 1938 (нужно изменить пароль/требуется смена пароля), 1351 (невозможно получить доступ к информации о домене), и 1355 (нет такого домена). На самом деле, существует более 15000 кодов ошибок Win32, но это позволит вам найти справочную информацию по тем, которые упомянуты здесь (или произвести поиск в файле winerror.h , который обычно можно найти в папке Program Files (x86)\Windows Kits\8.0\Include\shared). Удачной охоты!
  • callerSavesCredential Логическое значение, указывающее на то, что приложение сохранит учетные данные, а средство выбора учетных данных – нет. Значение по умолчанию - false. Когда свойство установлено в true, учетные данные сохраняются в защищенное системное расположение (не в хранилище учетных данных), если у приложения объявлена возможность Корпоративная аутентификация (Enterprise Authentication) (смотрите ниже).
  • ), показывающее изначальное состояние флага Сохранить учетные данные (Remember My Credentals): unselected, selected, или hidden.
  • authenticationProtocol Значение из перечисления AuthenticationProtocol(http://msdn.microsoft.com/library/windows/apps/windows.security.credentials.ui.authenticationprotocol.aspx): basic, digest, ntlm, kerberos, negotiate (по умолчанию), credSsp, и custom (в подобном случае вы должны предоставить строку в свойстве customAuthenticationProcotol). Обратите внимание на то, что в случае использования видов протокола аутентификации basic и digest, данные в CredentialPickerResults.credentialPassword не будут зашифрованы, к ним применимы те же соображения по обеспечению безопасности, что и пароль в виде обычного текста, который вы можете получить из собственного интерфейса.
  • Вот пример вызова средства выбора учетных данных с errorCode, указывающим на то, что предыдущая попытка входа не удалась:

    var options = new Windows.Security.Credentials.UI.CredentialPickerOptions();
    options.message = "Please enter your credentials";
    options.caption = "Sample App"; options.targetName = "Target"; options.alwaysDisplayDialog = true;
    options.errorCode = 1326; // Выводит "The username or password is incorrect." options.callerSavesCredential = true;
    options.authenticationProtocol = Windows.Security.Credentials.UI.AuthenticationProtocol.negotiate;
    options.credentialSaveOption = Windows.Security.Credentials.UI.CredentialSaveOption.selected;
    
    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(options)
    .done(function (results) {
    }
          

    Для того, чтобы прояснить взаимосвязь между свойствами callerSavesCredential, credentialSaveOption, и credentialSaved, следующая таблица перечисляет особенности их сочетаний:

    Возможность "Корпоративная аутентификация" Значение callerSavesCredential Значение credentialSaveOption Средство выбора сохраняет учетные данные Приложение сохраняет данные в хранилище учетных данных
    Нет true Selected Нет Да
    unselected или hidden Нет Нет
    false Selected Нет Да
    unselected или hidden Нет Нет
    Да true Selected Нет Да
    unselected или hidden Нет Нет
    false Selected Да (credentialSaved будет иметь значение true) Не обязательно
    unselected или hidden Нет Нет

    Первый столбец относится к возможности Корпоративная аутентификация (Enterprise Authentication) в манифесте приложения, что указывает на то, что приложение может работать с ресурсами корпоративной сети, которые требуют доменные учетные данные (подразумевается, что приложение исполняется на Windows 8 Enterprise Edition). В подобных случаях у средства выбора учетных данных есть другое безопасное хранилище (не относящееся к хранилищу учетных данных) в котором можно хранить учетные данные, таким образом приложению не нужно сохранять их самостоятельно. Более того, если средство выбора учетных данных сохраняет учетные данные и приложение вызывает его с параметром alwaysDisplayDialog установленным в false, параметр previousCredential может быть пустым, так как учетные данные будут загружены автоматически. Но без компьютера, подключеного к домену и вышеозначенной возможности, объявленной в манифесте, приложение должно поддерживать previousCredential для того, чтобы средство выбора файлов не появилось.

    Хранилище учетных данных

    Одной из причин, по которой приложение может постоянно запрашивать у пользователя учетные данные может быть то, что у приложения просто нет по-настоящему безопасного места для хранения учетных данных и последующего их получения, которое, кроме того, изолировано от любых других приложений. Это – задача хранилища учетных данных, для работы с которым используется API Windows.Security.Credentials.PasswordVault (http://msdn.microsoft.com/library/windows/apps/br227081.aspx ).

    С помощью хранилища, любые учетные данные могут быть представлены с помощью объекта ), как мы уже видели, когда говорили об API фоновой передачи данных. Вы можете создать и инициализировать учетные данные следующим образом:

    var cred = new Windows.Security.Credentials.PasswordCredential(resource, userName, password);

    Другая возможность заключается в создании неинициализированного объекта учетных данных и в индивидуальном заполнении его свойств:

    var cred = new Windows.Security.Credentials.PasswordCredential();
    cred.resource = "userLogin"
    cred.userName = "username";
    cred.password = "password";
          

    Объект, представляющий учетные данные так же содержит свойство типа ), которое называется properties, с его помощью можно управлять этими данными.

    В любом случае, когда вы получаете учетные данные от пользователя и хотите их сохранить, создайте объект PasswordCredential и передайте его методу PasswordVault.add:

    var vault = new Windows.Security.Credentials.PasswordVault();
    vault.add(cred);
          

    Обратите внимание на то, что если вы добавите в хранилище учетные данные со значениями a resource и userName , которые уже существуют, новые данные заменят старые. И если по какой-либо причине вы хотите удалить данные из хранилища вызовите метод PasswordVault.remove с этими учетными данными.

    Более того, даже хотя объект PasswordCredential выглядит содержащим имя пользователя и пароль, пароль может быть чем угодно, что вам нужно безопасно сохранить, например, маркером доступа. Как мы увидим в следующем разделе, при аутентификации посредством OAuth может предоставляться подобный маркер, в таком случае вам может понадобиться сохранить что-то вроде "Facebook_Token" в свойстве объекта, представляющего учетные resource, имя приложения в userName, и маркер – в свойстве password. Это – полностью оправданное и ожидаемое использование.

    Как только учетные данные попадают в хранилище, они остаются дам для использования при следующих запусках приложения, до тех пор, пока вы не вызовите метод remove или пользователь явным образом не удалит их, с помощью команды Панель управления > Учетные записи пользователей и семейная безопасность > Диспетчер учетных данных (Control Panel > User Accounts and Family Safety >Credential Manager). На доверенном ПК (что требует входа в него с использованием учетной записи Microsoft), Windows автоматически и безопасно перемещает содержимое хранилища на другие устройства (это можно выключить с помощью команды Параметры ПК > Синхронизация параметров > Пароли (PC Settings > Sync Your Settings > Passwords)). Это помогает создать единую рабочую среду для вашего приложения, когда пользователь перемещается между устройствами .

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

  • findAllByResource Возвращает массив (вектор) объектов учетных данных по заданному идентификатору ресурса. Подобным образом можно получить имя пользователя и пароль, которые переместились с другого устройства, так как приложение сохранило учетные данные на другом компьютере с тем же самым идентификатором ресурса.
  • findAllByUserName Возвращает массив (вектор) объектов учетных данных по заданному имени пользователя. Это полезно, если вы знаете имя пользователя и хотите получить все учетные данные для множества ресурсов, к которым подключено приложение.
  • retrieve Возвращает единственный объект учетных данных по заданному ресурсу идентификатора и имени пользователя. Опять же, сочетанию имени пользователя и ресурса соответствует только один объект в хранилище.
  • retrieveAll Возвращает вектор всех учетных данных, имеющихся в хранилище для данного приложения. Ветор содержит копию состояния хранилища и не обновляется, если происходят последующие обновления учетных данных в хранилище.
  • Есть небольшое различие между методами findAll и retrieve в вышеприведенном списке. Метод retrieve предоставляет полностью заполненные объекты учетных данных. А методы findAll, с другой стороны, возвращают объекты, в которых свойство password не заполнено. Это предотвращает дешифрование пароля на основе потенциально большого набора учетных данных. Для того, чтобы заполнить это свойство для каждого отдельного объекта, вызовите метод PasswordCredential.retievePassword.

    Для дальнейшей демонстрации работы с хранилищем учетных данных – код здесь очень прост – обратитесь к примеру "Хранилище учетных данных" ( http://code.msdn.microsoft.com/windowsapps/PasswordVault-f01be74a). Он показывает варианты работы для одного пользователя/одного ресурса (Сценарий 1), одного пользователя/несколькоих ресурсов (Сценарий 2), нескольких пользователей/нескольких ресурсов (Сценарий 3), а так же – полную очистку хранилища (Сценарий 4).

    Брокер веб-проверки подлинности

    Хотя приложения могут принимать учетные данные пользовтеля и управлять ими собственными силами, поддерживая пользователей, возможно, с возможностью создания учетных записей для конкретных приложений или конкретных сервисов (обычно с помощью чудо-кнопки Параметры, как обсуждалось в Главе 2 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript", а так же в материале "Руководство и контрольный список для элементов управления входом" (http://msdn.microsoft.com/library/windows/apps/hh965453.aspx ), может возникнуть необходимость использовать учетную запись, которую пользователь уже создал посредством другого OAuth-поставщика, остобенно когда вы хотите использовать ресурсы этого поставщика. Вероятно, вы уже сталкивались с этим на многих веб-сайтах, куда можно войти через другой сайт, наподобие Facebook. Конечно, это обычно означает переход с исходного сайта на сайт поставщика – процесс, который отлично происходит в веб-браузере, но не столь привлекателен в контексте приложения!

    Для этой цели Windows предоставляет Брокера веб-проверки подлинности (Web Authentication Broker), который делает то же самое, не покидая контекст приложения. Приложение предоставляет URI для страницы проверки подлинности на внешнем сайте (необходимо использовать схему URI-схему https://, в противном случае вы получите ошибку, вызванную неподходящим параметров). Затем брокер создает новый хост-процесс для веб в его собственном контейнере приложения, в который и загружает указанную веб-страницу. Пользовательский интерфейс для этого процесса показан в виде находящегося поверх приложения диалогового окна, рис 8.2, для чего я использовал Сценарий 1 примера "Брокер веб-проверки подлинности" (http://code.msdn.microsoft.com/windowsapps/Web-Authentication-d0485122 ).

    (рис 8.2) Пример использования брокера веб-проверки подлинности со страницей входа в систему сервиса Facebook

    Примечание. Для того, чтобы запустить пример, вам понадобятся ID приложения для каждого из поставщиков аутентификации в различных сценариях. Для Facebook в Сценарии 1, посетите http://developers.facebook.com/setup и создайте App ID/API Key для тестового приложения.

    В случае с Facebook, процесс аутентификации включает в себя больше, чем просто проверка учетных данных пользователя. Кроме того, нужно получить различение на других возможности, которыми собирается пользоваться приложение (пользователь может независимо от приложения отменить их на сайте Facebook). В результате, процесс аутентификации может включать в себя переходы на дополнительные страницы, каждая из которых будет отображаться в брокере веб-проверки подлинности, как показано на рис 8.3. В данном случае идентификатор приложения, ProgrammingWin8_AuthTest, это тот, что я только что создал посредством страницы настроек разработчика Facebook для целей этой демонстрации.

    (рис 8.3) Дополнительные шаги аутентификации в Facebook внутри брокера веб-проверки подлинности

    В интерфейсе брокера веб-проверки пользователь может пройти через множество страниц сайта поставщика (обратите внимание на то, что кнопка Назад, около заголовка "Сonnecting to a service" (Подключение к сервису) полностью закрывает это окно). Но все это приводит к к вопросу: как брокер узнает, что аутентификация завершилась? Последний шаг в процессе аутентификации на правой части рис 8.3. – нажатие на кнопку Allow (Разрешить) , после чего обычно Facebook отображает страницу с информацией об успешном входе. В контексте приложения, однако, нам не нужно отображать подобную страницу – скорее нужно закрыть окно брокера и вернуться в приложение с результатом аутентификации. Более того, многие OAuth-поставщики даже не имеют подобной страницы. Что же нам делать?

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

    Как часть этого процесса, Facebook сохраняет информацию о различных разрешениях на собственном сервере для каждого конкретного пользователя, поэтому, если приложение снова запустит процесс аутентификации, пользователь не увидите тех же страниц, что показаны на рис 8.3. Пользователь может, конечно, управлять этими разрешениями, когда посещает страницу Facebook через веб-браузер, если пользователь удалит здесь информацию о приложении, то при повторном входе через приложение снова будут показаны те же страницы.

    В WinRT брокер представлен классом ). Аутентификация производится с помощью его методов authenticateAsync. Я написал здесь "методов", так как имеется два их варианта. Мы посмотрим на один из них здесь и вернемся ко всторому в следующем разделе, "Режим единого входа".

    Первый вариант метода authenticateAsync принимает три аргумента:

  • ) (скомбинированных с помощью побитового OR). Возможные значения: none (по умолчанию), silentMode (не отображается интерфейс), useTitle (возвращает в результатах заголовок окна веб-страницы), useHttpPost (возвращает в результатах тело страницы), и useCorporateNetwork (для вывода в контейнере приложения веб-страниц с возможностями Частные сети (клиент и сервер) (Private Networks (Client Server)), Корпоративная аутентификация (Enterprise Authentication), Общие сертификаты пользователей (Shared User Sertificates); кроме того, приложение должно объявить эти возможности).
  • requestUri URI (Windows.Foundation.Uri) для страницы аутентификации поставщика с параметрами, которые нужны сервису; повторюсь, здесь необходимо использовать схему URI https://.
  • callbackUri URI (Windows.Foundation.Uri) конечной страницы, отображаемой в процессе аутентификации у поставщика. Брокер использует этот адрес для определения момента закрытия собственного интерфейса .
  • Результат, передаваемый обработчику завершения ). Он содержит следующие свойства: ), которое может принимать значения success, userCancel, или errorHttp), responseData (строка, содержащая заголовок страницы и ее тело, если, соответственно, установлены опции useTitle и useHttpPost), и responseErrorDetail (номер ошибки HTTP).

    Вообще говоря, приложению особенно интересно содержимое responseData, так как здесь будет содержаться маркер или другие ключи, которые могут понадобиться ему позже. Посмотрим на это снова, в контексте Сценария 1 примера "Брокер веб-проверки подлинности" (http://code.msdn.microsoft.com/windowsapps/Web-Authentication-d0485122 ). Установим точку основа в обработчике завершения authenticateAsync (строка 59 или поблизости), и запустим пример, введем ID приложения, который был создан ранее и нажмем Launch (Запустить). (Обратите внимание на то, что параметр callbackUri установлен в https://www.facebook.com/connect/login_success.html, это страница, на которой завершается процесс аутентификации).

    В случае с Facebook, responseData содержит строку такого вида:

            https://www.facebook.com/connect/login_success.html#access_token=<token>
            expires_in=<timeout>
          

    Здесь в <token> Содержится куча алфавитно-цифровой абракадабры, <timeout>

  • это некоторый период, заданный Facebook. Если вы вызовете какое-нибудь API Facebook, что весьма вероятно, так как вы не случайно проходите аутентификацию через Facebook, <token>
  • это настоящее богатство, так как именно с его помощью вы аутентифицируете пользователя, когда выполняете вызовы к этому API.
  • Этот маркер доступа затем сохраняют в хранилище учетных данных для последующего использования, когда приложение будет перезапущено после приостановки или остановки. (В случае с Facebook, вам не нужно беспокоиться об истечении срока действия этого маркера, так как API обычно сообщает об этом как об ошибке и имеет встроенный процесс обновления маркера). Что-то похожее вам придется делать при работе с другими поставщиками аутентификация, обращаясь, конечно, к их документации, которая сообщит о том, что вы получите в ответе сервера и как использовать и/или обновлять ключи или маркеры при необходимости.

    В целом, ключевое преимущество веб-аутентификации это то, что пользователь никогда не предоставляет учетные данные приложению – пользователь передает их лишь гораздо более доверенному поставщику. С точки зрения приложения, так же, ему никогда не требуется управлять этими учетными данными, лишь токеном, который возвращает поставщик. По той же причине, при запуске брокера, который мы видели здесь, всегда будет отображаться страница входа с пустыми полями, независимо от флага Оставаться в системе (Keep Me Logged In), так как приложение не хранит подобных данных, и любые куки и состояния сессии находятся внутри окружения брокера и не сохраняются. Таким образом, если приложению нужно дать пользователю доступ к тому же сервису с другими учетными данными, ему достаточно запустить брокер, как ранее, и заменить токены или ключи, которые были сохранены при последнем сеансе аутентификации.

    Говоря о поставщиках, страница про OAuth в Википедии ( http://ru.wikipedia.org/wiki/OAuth) содержит перечисление существующих поставщиков аутентификации. Пример "Брокер веб-проверки подлинности", в свою очередь, показывает как работать с Facebook (Сценарий 1), Twitter (Сценарий 2), Flickr (Сценарий 3), и Google/Picasa (Сценарий 4), и так же предоставляет общий интерфейс для любых других сервисов (Сценарий 5).

    Полезно просмотреть эти разные сценарии, так как Facebook и Google используют протокол OAuth 2.0, requestUri для каждого выглядитдовольно простым (если исключить перенос слов:

    https://www.facebook.com/dialog/oauth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    scope-read_streamdisplay=popupresponse_type=token
    
    https://accounts.google.com/o/oauth2/auth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    response_type=codescope=http://picasaweb.google.com/data
    https://www.facebook.com/dialog/oauth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    scope-read_streamdisplay=popupresponse_type=token
          

    Здесь <client_id>и <redirectUri> заменяется на то, что задано приложением. Twitter иFlickr, в свою очередь, используют вместо этого протокол OAuth 1.0a, в итоге, требуется включать длинный маркер OAuth в аргумент requestUri для authenticateAsync. Подробности вы можете увидеть в коде примера.

    Совет. События брокера веб-проверки подлинности можно просмотреть окне Просмотр журналов событий (Event Viewer) в разделе Журналы приложений и служб > Microsoft > Windows > WebAuth> Operational (Application And Services Logs >Microsoft > Windows > WebAuth > Operational). Это может быть полезным для целей отладки, так как здесь можно увидеть данные, которые, в противном случае, скрыты за непрозрачным окружением брокера.

    Режим единого входа

    Все, касающееся хранилища учетных данных и брокера веб-проверки подлинности, отлично работает для минимизации того, как часто приложение донимает пользователя вопросами о вводе учетных данных. Когда речь идет об отдельном приложении, очень хороша возможность один раз запросить учетные данные и не запрашивать их снова до тех пор, пока пользователь явным образом не выйдет из системы. Но как насчет нескольких приложений. Представьте себе, что вы установили несколько десятков или сотен приложений из Магазина Windows, использующих внешних поставщиков аутентификации. Это может означать, что вы будете вводить учетные данные для входа в аккаунты Facebook, Twitter, Google, LinkedIn, Tumblr, Yahoo, или Yammer в каждое приложение, которое их использует. Очевидно, в каждом отдельном приложении это нужно будет лишь раз, но общий эффект оказывается утомляющим и надоедливым!

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

    Концепция режима единого входа (SSO) в этом и заключается: проверка подлинности пользователя в одном приложении (или во всей системе, в случае с учетной записью Microsoft) приводит к возможности входа в другие приложения, которые используют того же поставщика. В то же время, каждое приложение обычно должно получить собственные ключи доступа или маркеры, так как их не следует делать общими для разных приложений. В итоге весь фокус заключается в том, чтобы эффективно произвести тот же процесс аутентификации, который мы видели, только сделать его, не показывая пользовательский интерфейс до тех пор, пока это действительно не будет нужно.

    Это можно реализовать с помощью брокера веб-проверки подлинности с помощью одного из вариантов authenticateAsync, который принимает лишь аргументы options и requestUri. В данном случае options часто устанавливается в WebAuthenticationOptions.silentMode для того, чтобы предотвратить показ интерфейса рокера (но это не обязательно).

    Для того, чтобы режим silentMode заработал, брокеру все еще нужно узнать, когда завершится процесс проверки подлинности. Поэтому, какой же callbackUri ему использовать для сравнения и как поставщик узнает то, что ему нужно? Это напоминает ситуацию, когда брокер находится в системе, всегда скрытый, в то время, Как поставщик терпеливо ожидает ввода данных на веб-страницу, которая полностью невидима! Что, на самом деле происходит, это то, что authenticateAsync ожидает, когда поставщик перейдет по особому callbackUri , которое выглядит как ms-app://<app_package> /<secret_sauce>, после чего результат ответа поставщика будет передан в виде асинхронного результата.

    Конечно, данный URI неичего не значит для поставщика …если только его не оповестили об этом заранее и он не ожидает появления подобного URI в своей среде.

    Это сообщает нам о том факте, что режим единого входа работает только если провайдер имеет средства (API или что-то вроде того), посредством которого приложение может сообщить о своих намерениях. Для того, чтобы это понять, рассмотрим полный рабочий процесс "тихой" аутентификации:

  • Приложение, которое желает использовать режим единого входа, подписывается, с помощью одного из двух средств, на получение собственного URI ms-app://, который так же называется SID URI. Во-первых, это возможно с помощью вызова статического метода WebAuthenticationBroker.getCurrentApplicationCallbackUri. Этот вызов возвращает объект Windows.Foundation.Uri, строковое свойство которого absoluteUri, это как раз то, что вам нужно. Во-вторых, это можно реализовать на странице Магазина Windows Информационная панель > Управление облачными службами > Дополнительные функции > Проверка подлинности приложения (Dashboard > Manage Your Cloud Services > Advanced Features > Application Authentication), где вы сможете увидеть строку, выглядящую примерно так: ms-app://s-1-15-2-477157379-2961032073-432767880-3229792171-202870256-1369967874-2241987394/.
  • Если нужно, приложение затем вызывает API поставщика для регистрации этого SID URI (обычно у поставщика есть страница для указания приложения, где вводят эти данные).
  • При создании аргументов requestUri для authenticateAsync, приложение добавляет свой SID URI в качестве значения для параметра redirect_uri=.
  • Приложение вызывает authenticateAsync с опцией silentMode.
  • Когда поставщик обработает параметры requestUri, он проверяет, зарегистрировано ли значение redirect_uri, и, если это не так, отвечает сообщением об ошибке.
  • Производя проверку приложения, поставщик затем, не задавая вопросов (если возможно) производит проверку подлинности и переходит по redirect_uri, не забыв включить маркеры и ключи доступа в данные ответа.
  • Брокер веб-проверки пользователя обнаруживает этот переход и сравнивает его адрес со своим callbackUri. Обнаружив совпадение, брокер может завершить асинхронную операцию и предоставить приложению данные ответа поставщика.
  • Опять же, у поставщика должны быть средства, с помощью которых разработчик или приложение могут зарегистрировать SID URI, он должен проверить SID URI, когда оно оказывается в запросе на проверку подлинности, и должен выдать подходящий ответ на эту страницу, когда проверка подлинности завершена. Таким образом, поставщик или приложение ответственны за регистрацию SID URI и за включение его в requestUri. (Ух ты, сколько же URI!)

    При всем этом, все еще возможно, что проверка подлинности может не удастся по каким-то другим причинам. Например, если пользователь не установил полномочия приложения для этого (как в случае с Facebook), "тихая" проверка подлинности не возможна. Таким образом, приложение пытается использовать режим единого входа, вызывает сначала authenticateAsync соответствующего вида, а если это не удается, пытается вызвать его более длинный вариант (с показом пользовательского интерфейса), как описано в предыдущем разделе.

    Режим единого входа в службу Live Connect

    Так как различные службы Microsoft, такие, как Hotmail, являются поставщиками OAuth, возможно использовать брокер веб-проверки подлинности с учетной записью Microsoft (с такой, как учетные записи Hotmail, Live, и MSN). (У меня все еще есть учетная запись электронной почты @msn.com, которую я получил в 1996!). Подробности можно найти на странице "OAuth 2.0" ( http://msdn.microsoft.com/library/live/hh243647.aspx) в Центре разработчиков Live Connect.

    Тем не менее, учетные записи Live Connect находятся в более привилегированном положении, так как их можно использовать для входа в Windows, или подключить к доменной учетной записи для той же цели. Многие из встроенных приложений, такие, как Mail (Почта), Calendar (Календарь), SkyDrive, People (Люди) и Магазин Windows, работают с той же учетной записью. Таким образом, это то, чем, возможно, захотят воспользоваться многие другие приложения, так как подобная аутентификация дает доступ к тем же данным служб Live, с которыми работают встроенные приложения. API Live Services выглядит как WL.login, он доступен при Live SDK и добавляет в проект соответствующие ссылки. Для того, чтобы начать работу, посетите страницу документации по Live Connect (http://msdn.microsoft.com/ru-ru/library/live/ff621314.aspx ) и почитайте следующие материалы:

  • Live Connect, домашняя страница (http://msdn.microsoft.com/library/windows/apps/hh770845.aspx )
  • Центр разработчиков Live Connect (http://msdn.microsoft.com/library/live/hh826551.aspx )
  • Руководство по единому входу и подключенным учетным записям ( http://msdn.microsoft.com/library/windows/apps/jj193591.aspx)
  • Руководство по взаимодействию с пользователем при входе в учетную запись Майкрософт (http://msdn.microsoft.com/library/windows/apps/hh968443.aspx )
  • Единый вход с учетной записью Майкрософт (http://msdn.microsoft.com/library/windows/apps/hh465097.aspx )
  • Краткое руководство: персонализация приложения (http://msdn.microsoft.com/library/windows/apps/hh920269.aspx )
  • Пример "Авторизация с учетной записью Microsoft" (http://code.msdn.microsoft.com/windowsapps/Windows-account-authorizati-7c95e284 )
  • Материалы блога для разработчиков приложения для Windows 8 "Внедрение функций единого входа и SkyDrive в приложения для Windows 8 с помощью Live SDK" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/03/22/skydrive-windows-8-live-sdk.aspx ) и "Рекомендации по добавлению функции единого входа в приложения с помощью Live SDK" ( http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/07/02/live-sdk.aspx).
  • Вы можете видеть, что работа со службами Live – весьма обширная тема, поэтому я оставляю ее вышеприведенным ресурсам. Хочу упомянуть один из ключевых моментов. Пользователь может войти в Windows с использованием доменной учетной записи, которая не подключена к учетной записи Microsoft в разделе Параметры ПК > Пользователи (PC Settings > Users). В подобном случае первый вызов WL.login, исходящий от любого приложения, отобразит диалоговое окно для входа в учетную запись Microsoft, как показано на рис 8.4. Как только пользователь введет здесь учетные данные, осуществится вход и во все остальные приложения, которые используют учетную запись Microsoft.

    (рис 8.4) Диалоговое окно входа в учетную запись Microsoft

    Профиль пользователя (и изображение экрана блокировки)

    Любой разговор об учетных данные пользователя вызывает вопрос о доступе к дополнительной информации пользователя. То, что доступно приложениям для Магазина Windows, предоставляется с помощью API Windows.System.UserProfile (http://msdn.microsoft.com/library/windows/apps/windows.system.userprofile.aspx ), где мы можем найти классы, относящиеся к предмету нашего интереса.

    Первый – это класс ) для того, чтобы увидеть демонстрацию этого.

    >Второй – это объект ), к которому мы вернемся к Главе 6.

    Третий – это класс ), возможности которого отражены на странице Параметры ПК > Персонализация > Аватар (PC Settings > Personalize > Account picture):

  • Имя пользователя (User name) Если свойство nameAccessAllowed установлено в true, приложение может вызывать методы getDisplayNameAsync, getFirstNameAsync, и getLastNameAsync, каждый из которых предоставляет строку в обработчик завершения. Если nameAccessAllowed установлено в false, эти методы выполняются, до завершения, но возвращают пустой результат. Кроме того, обратите внимание на то, что получение имени (first name) и фамилии (last name) доступно лишь из учетной записи Microsoft
  • Изображение пользователя (User picture) Его можно получить, воспользовавшись методом ): smallImage, largeImage, и video.
  • Если свойство ): success, failure, changeDisabled (accountPictureChangeEnabled установлено в false), largeOrDynamicError (изображение слишком велико), fileSizeError (файл слишком велик), или videoFrameSizeError (размер кадра видео слишком велик),
  • Событие accountpicturechanged вызывается, когда изображение (или изображения) пользователя изменяется. Помните о том, что так как это – событие, исходящие из WinRT, вам следует вызвать removeEventListener, если вы не намерены прослушивать это событие во время работы приложения.
  • Демонстрацию этих возможностей можно найти в примере "Имя пользователя и изображение учетной записи" (http://code.msdn.microsoft.com/windowsapps/Account-picture-name-sample-912baff1 ). Сценарий 1 получает отображаемое имя, Сценарий 2 получает имя и фамилию пользователя (если они доступны), Сценарий 3 получает изображение учетной записи и видео, Сценарий 4 позволяет изменить изображения и видео, и прослушивать событие изменения изображений.

    Совет. Для того, чтобы получить изображение профиля из Live Connect, можно воспользоваться следующим вызовом API: https://apis.live.net/v5.0/me/picture?access_token=<ACCESS_TOKEN> Кроме того, этот пример показывает объявление Поставщик изображений для учетных записей(Account Picture Provider), благодаря чему приложение отображается в окне Параметры ПК > Персонализация, в разделе Приложения для создания аватара (Create an Account Picture):

    В данном случае приложение-пример не предоставляет изображение напрямую, но активируется со Сценарием 4. Реальное приложение, такое, как Camera (Камера), которая есть в Параметрах ПК по умолчанию, автоматически задаст изображение учетной записи, когда оно будет получено с помощью его интерфейса. Откуда приложение знает, как это сделать? Ответ находится в специальной схеме URI, посредством которой активируется приложение. Таким образом, если вы сделали объявление Поставщик изображений для учетных записей(Account Picture Provider) в манифесте, приложение будет активировано с видом активации protocol (смотрите Главу 1), где схема URI начинается с ms-accountpictureprovider. Вы можете увидеть, как обрабатывается такая активация в файле js/default.js:

    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.protocol) {
    // Проверяет, совпадает ли protocol со схемой "ms-accountpictureprovider"
    if (eventObject.detail.uri.schemeName === "ms-accountpictureprovider") {
    // Приложение было активировано с помощью команды задания аватара в разделе Персонализация в Параметрах ПК.
    // Здесь можно выполнить действия по предоставлению пользователю интерфейса для
    // выбора изображения учетной записи.
    }
          

    Возвращаясь к классу UserInformation, можно сказать, что так же он предоставляет немного больше подробностей для доменных учетных записей, предполагая, что у приложения, в манифесте, объявлена возможность Корпоративная аутентификация (Enterprise Authentication):

  • getDomainNameAsync предоставляет полностью определенное доменное имя пользователя в виде строки, в форме
    <domain>
      \<user>
       где <domain>

    Это полное имя контроллера домена, как, например, mydomain.corp.ourcompany.com.

  • getPrincipalNameAsync Предоставляет имя субъекта в виде строки. В применении к Active Directory, это имя для входа, в интернет-стиле (известное как имя субъекта-пользователя (user principal name), или UPN), которое короче и проще, чем доменное имя, объединяя имя для входа в систему и адрес электронного почтового ящика. Обычно – это адрес электонной почты наподобие user@ourcompany.com.
  • ).
  • Использование этих методов показано в примере "Доменное имя пользователя" (http://code.msdn.microsoft.com/windowsapps/User-domain-name-sample-85ce3e49 ).

    Шифрование, расшифровка, защита данных и сертификаты

    Авторизация и учетные записи – это темы, связанные с безопасностью, поэтому хорошо будет завершить этот раздел кратким разбором других API, которые находятся в пространстве имен Windows.Security, одно из которых, брокер веб-проверки пользователей, мы уже рассматривали.

    Первое - это ). Здесь вы можете найти класс CryptographicBuffer, который позволяет кодировкить и декодировать строки в шестнадцатеричном формате и в формате base64 (UTF-8 или UTF-16), предоставляет набор случайных числе и байтовый массив, полный таких чисел. Обратитесь к Сценарию 1 примера "Криптография в WinRT" (http://code.msdn.microsoft.com/windowsapps/CryptoWinRT-54ff3d9f ) чтобы увидеть демонстрацию его применения, а так же, к Сценариям 2 и 3 примера "Брокер веб-проверки подлинности". Кодировка base64 WinRT полностью совместима с функциями JavaScript atob и btoa.

    Далее, это ), который применим к шифрованию и расшифровке с использованием различных алгоритмов. Смотрите материал "Шифрование" ( http://msdn.microsoft.com/library/windows/apps/hh464976.aspx), Сценарии 2 – 8 примера "Криптография в WinRT", и, снова Сценарии 2 и 3 примера "Брокер веб-проверки подлинности"

    Третье – ), единственный класс которого, ) и к сценариям 9 и 10 примера "Криптография в WinRT".

    Четвертое - ) предоставляет несколько классов, с помощью которых можно создавать запросы сертификатов и устанавливать отклики сертификатов. Обратитесь к материалу "Работа с сертификатами" (http://msdn.microsoft.com/library/windows/apps/hh465044.aspx ) и к примеру "Работа с сертификатом" (http://code.msdn.microsoft.com/windowsapps/Certificate-Enrollment-SDK-7ecf4976 ) для того, чтобы узнать подробности.

    И, наконец, полезно по меньшей мере упомянуть API из ), имеется пример "EAS-политики для почтового клиента" (http://code.msdn.microsoft.com/windowsapps/Web-authentication-for-b9b8ed1a ). Думаю, вы знаете, зачем вам это может понадобиться.

    Страницы:

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

    Есть два основных подхода по работе с учетными данными. Первая, вы можете собирать учетные данные напрямую, с помощью интерфейса Средства выбора учетных данных, или с помощью собственного пользовательского интерфейса. В любом случае, однако, следующий вопрос заключается в том, как организовать безопасное хранение учетных данных, для чего у нас имеется API хранилища учетных данных (Credential Locker API). Хранилище позволяет приложения получать учетные данные в последующих сеансах работы, таким образом, ему не нужно каждый раз просить пользователя вводить эти учетные данные (что довольно утомительно, уверен, вы это знаете).

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

    По этой причине – хорошая идея делегировать эти действия другим. например, интерфейс средства выбора файлов будет, по умолчанию, шифровать пароли прежде чем передаст их вашему приложению. Или вы можете использовать второй подход для работы с учетными данными, когда приложение проверяет подлинность пользователя с помощью другого поставщика услуг, такого, как Microsoft Live Connect, Facebook, Flickr, Yahoo, и так далее. При этом поставщик выполняет всю работу по проверке подлинности и приложению лишь нужно сохранить соответствующие маркеры или другие ключи доступа для данного сервиса. Основное преимущества интегрированной проверки подлинности подобного вида заключается в том, что приложение никогда не работает с учетными данными самостоятельно, и, таким образом, ему не нужно беспокоиться об их безопасности. (Однако, приложению следует шифровать маркеры или ключе доступа, если оно их хранит. Хранилище учетных данных можно использовать и для этой цели.)

    В большинстве случаев этот процесс включает в себя агента, который называется Брокер веб-проверки подлинности (Web Authentication Broker), который, в частности, работает с протоколами OAuth/OpenID и поставщиками услуг, обычно расположенными в Веб. Microsoft Live Connect – это особый случай, так как учетная запись Microsoft, используемая с ним может, кроме того, использоваться для входа в Windows. (Проверка подлинности через Live Connect так же предоставляет приложению доступ к другим данным из сервисов Live, в том числе, к Calendar, Messenger, и SkyDrive.)

    Одно из других замечательных преимуществ этого второго подхода заключается в возможности работы в режиме единого входа (single sign on, SSO). Это означает, что когда пользователь авторизовался у какого-либо OAuth-поставщика в одном приложении, ему часто не нужно осуществлять вход в другие приложения, которые исопльзуют того же поставщика (если приложение сочтет это нужным). В случае с Live Connect, приложения может никогда не понадобиться запрашивать учетные данные, если та же самая учетная запись Microsoft использована для входа в Windows или связана с входом пользователя в домен.

    В этом разделе мы так же кратко рассмотрим – и это все, что нужно в данном случае – информацию профиля пользователя, доступную с помощью API WinRT, вместе с API для шифрования и дешифровки. Помимо этого, я расскажу о двух других материалах по теме. Первый, это "Защита соединений и проверка подлинности запросов" (http://msdn.microsoft.com/library/windows/apps/hh986970.aspx ). Второй – это пример "Банковское приложение Магазина Windows со строгой проверкой подлинности" ( http://code.msdn.microsoft.com/windowsapps/Metro-style-banking-app-7d963c00), которое демонстрирует пример безопасной проверки подлинности и обмена данными через Интернет. Полное описание этого примера можно найти вматериале "Банковское приложение Магазина Windows: обзор кода" (http://msdn.microsoft.com/library/windows/apps/Hh464943 ), поэтому здесь мы не будем его рассматривать.

    Совет по дизайну. Существует множество руководств по дизайну для различных сценариев входа в систему, касающиеся ситуаций, когда приложению требуется вход в систему для работы, или когда вход необязателен. Эти темы, а так же рекомендации о том, где разместить интерфейс для входа в систему и управления учетной записью или профилем, обсуждаются в материале "Руководство и контрольный список для элементов управления входом" (http://msdn.microsoft.com/library/windows/apps/hh965453.aspx ).

    Пользовательский интерфейс средства работы с учетными данными

    Так же, как WinRT предоставляет встроенный интерфейс для выбора файлов, имеется и встроенный пользовательский интерфейс для ввода учетных данных: ).

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

    (рис 8.1) Интерфейс средства выбора учетных данных выводится, как и диалоговое окно сообщения, поверх приложения

    Результаты из pickAsync, переданные обработчику завершения, это объект CredentialPickerResults (http://msdn.microsoft.com/library/windows/apps/windows.security.credentials.ui.credentialpickerresults.aspx ), который имеет следующие свойства. Когда вы введете какие-нибудь учетные данные в примере, вы увидите их значения, отраженные в выходных данных примера:

  • credentialuserName Строка, которая содержит введенное имя пользователя.
  • credentialPassword Строка, которая содержит пароль (обычно зашифрованный, в зависимости от параметров протокола проверки подлиности).
  • credentialDomainName Строка, содержащая имя домена, если он введен вместе с именем прользователя, (в таком виде: <domain> \<username>).
  • credentialSaved Логическое значение, которое показывает, будет ли производиться автоматическое сохранение введенных учетных данных. Это зависит от параметра средства выбора учетных данных, как обсуждается ниже.
  • ), отображает состояние флага Сохранить учетные данные (Remember My Credentals): unselected, selected, или hidden. Скоро мы рассмотрим обработку этого значения.
  • errorCode Содержит ноль, если ошибок нет, в противном случае – код ошибки.
  • credential Значение типа IBuffer, содержащее учетные данные в виде непрозрачного массива байтов. Его вы можете сохранить, если нужно, в составе состояния приложения и позднее передать обратно средству выбора учетных данных. Как это сделать, мы скоро увидим.
  • Три сценария в примере показывают различные параметры, которые вы можете использовать для вызова средства выбора учетных данных. Для этих целей присутствует три различных варианта .:

    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(targetName, message)
    .done(function (results) {
    }
          

    Второй вариант принимает те же аргументы вместе со строкой заголовка, которая появляется вместо текста "Credential Picker Sample" на рис 8.1.

    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(targetName, message, caption)
    .done(function (results) {
    }
          

    Третий вариант принимает объект ), который имеет те же свойства:строки targetName, message, и caption , вместе со следующими:

  • previousCredential Значение типа IBuffer с непрозрачной информацией об учетных данных, которые были предоставлены при предыдущем запуске средства (смотрите CredentialPickerResults.credential выше).
  • alwaysDisplayDialog Логическое значение, указывающее на то, отображается ли диалоговое окно. Значение по умолчанию – false, но это применимо лишь в том случае, если вы заполнили свойство previousCredential (с исключением для компьютеров, подключенных к домену – смотрите таблицу ниже). Цель его использования заключается в том, чтобы показать диалоговое окно, когда сохраненные учетные данные могут быть неверными, и от пользователя ожидается предоставление новых данных.
  • ) (по умолчанию ERROR_SUCCESS) которое можно отформатировать и показать в диалоговом окне. Это значение используют, когда учетные данные сначала получены от средства их выбора, но оказалось, что эти учетные данные подходят и нужно снова запустить диалоговое окно для их ввода. Вместо того, чтобы предоставлять собственное сообщение, вы можете просто получить код ошибки и позволить системе сделать все остальное. Наиболее часто встречающиеся здесь ошибки имеют следующие коды: 1326 (ошибка входа), 1330 (истек пароль), 2202 (неправильное имя пользователя), 1907 или 1938 (нужно изменить пароль/требуется смена пароля), 1351 (невозможно получить доступ к информации о домене), и 1355 (нет такого домена). На самом деле, существует более 15000 кодов ошибок Win32, но это позволит вам найти справочную информацию по тем, которые упомянуты здесь (или произвести поиск в файле winerror.h , который обычно можно найти в папке Program Files (x86)\Windows Kits\8.0\Include\shared). Удачной охоты!
  • callerSavesCredential Логическое значение, указывающее на то, что приложение сохранит учетные данные, а средство выбора учетных данных – нет. Значение по умолчанию - false. Когда свойство установлено в true, учетные данные сохраняются в защищенное системное расположение (не в хранилище учетных данных), если у приложения объявлена возможность Корпоративная аутентификация (Enterprise Authentication) (смотрите ниже).
  • ), показывающее изначальное состояние флага Сохранить учетные данные (Remember My Credentals): unselected, selected, или hidden.
  • authenticationProtocol Значение из перечисления AuthenticationProtocol(http://msdn.microsoft.com/library/windows/apps/windows.security.credentials.ui.authenticationprotocol.aspx): basic, digest, ntlm, kerberos, negotiate (по умолчанию), credSsp, и custom (в подобном случае вы должны предоставить строку в свойстве customAuthenticationProcotol). Обратите внимание на то, что в случае использования видов протокола аутентификации basic и digest, данные в CredentialPickerResults.credentialPassword не будут зашифрованы, к ним применимы те же соображения по обеспечению безопасности, что и пароль в виде обычного текста, который вы можете получить из собственного интерфейса.
  • Вот пример вызова средства выбора учетных данных с errorCode, указывающим на то, что предыдущая попытка входа не удалась:

    var options = new Windows.Security.Credentials.UI.CredentialPickerOptions();
    options.message = "Please enter your credentials";
    options.caption = "Sample App"; options.targetName = "Target"; options.alwaysDisplayDialog = true;
    options.errorCode = 1326; // Выводит "The username or password is incorrect." options.callerSavesCredential = true;
    options.authenticationProtocol = Windows.Security.Credentials.UI.AuthenticationProtocol.negotiate;
    options.credentialSaveOption = Windows.Security.Credentials.UI.CredentialSaveOption.selected;
    
    Windows.Security.Credentials.UI.CredentialPicker.pickAsync(options)
    .done(function (results) {
    }
          

    Для того, чтобы прояснить взаимосвязь между свойствами callerSavesCredential, credentialSaveOption, и credentialSaved, следующая таблица перечисляет особенности их сочетаний:

    Возможность "Корпоративная аутентификация" Значение callerSavesCredential Значение credentialSaveOption Средство выбора сохраняет учетные данные Приложение сохраняет данные в хранилище учетных данных
    Нет true Selected Нет Да
    unselected или hidden Нет Нет
    false Selected Нет Да
    unselected или hidden Нет Нет
    Да true Selected Нет Да
    unselected или hidden Нет Нет
    false Selected Да (credentialSaved будет иметь значение true) Не обязательно
    unselected или hidden Нет Нет

    Первый столбец относится к возможности Корпоративная аутентификация (Enterprise Authentication) в манифесте приложения, что указывает на то, что приложение может работать с ресурсами корпоративной сети, которые требуют доменные учетные данные (подразумевается, что приложение исполняется на Windows 8 Enterprise Edition). В подобных случаях у средства выбора учетных данных есть другое безопасное хранилище (не относящееся к хранилищу учетных данных) в котором можно хранить учетные данные, таким образом приложению не нужно сохранять их самостоятельно. Более того, если средство выбора учетных данных сохраняет учетные данные и приложение вызывает его с параметром alwaysDisplayDialog установленным в false, параметр previousCredential может быть пустым, так как учетные данные будут загружены автоматически. Но без компьютера, подключеного к домену и вышеозначенной возможности, объявленной в манифесте, приложение должно поддерживать previousCredential для того, чтобы средство выбора файлов не появилось.

    Хранилище учетных данных

    Одной из причин, по которой приложение может постоянно запрашивать у пользователя учетные данные может быть то, что у приложения просто нет по-настоящему безопасного места для хранения учетных данных и последующего их получения, которое, кроме того, изолировано от любых других приложений. Это – задача хранилища учетных данных, для работы с которым используется API Windows.Security.Credentials.PasswordVault (http://msdn.microsoft.com/library/windows/apps/br227081.aspx ).

    С помощью хранилища, любые учетные данные могут быть представлены с помощью объекта ), как мы уже видели, когда говорили об API фоновой передачи данных. Вы можете создать и инициализировать учетные данные следующим образом:

    var cred = new Windows.Security.Credentials.PasswordCredential(resource, userName, password);

    Другая возможность заключается в создании неинициализированного объекта учетных данных и в индивидуальном заполнении его свойств:

    var cred = new Windows.Security.Credentials.PasswordCredential();
    cred.resource = "userLogin"
    cred.userName = "username";
    cred.password = "password";
          

    Объект, представляющий учетные данные так же содержит свойство типа ), которое называется properties, с его помощью можно управлять этими данными.

    В любом случае, когда вы получаете учетные данные от пользователя и хотите их сохранить, создайте объект PasswordCredential и передайте его методу PasswordVault.add:

    var vault = new Windows.Security.Credentials.PasswordVault();
    vault.add(cred);
          

    Обратите внимание на то, что если вы добавите в хранилище учетные данные со значениями a resource и userName , которые уже существуют, новые данные заменят старые. И если по какой-либо причине вы хотите удалить данные из хранилища вызовите метод PasswordVault.remove с этими учетными данными.

    Более того, даже хотя объект PasswordCredential выглядит содержащим имя пользователя и пароль, пароль может быть чем угодно, что вам нужно безопасно сохранить, например, маркером доступа. Как мы увидим в следующем разделе, при аутентификации посредством OAuth может предоставляться подобный маркер, в таком случае вам может понадобиться сохранить что-то вроде "Facebook_Token" в свойстве объекта, представляющего учетные resource, имя приложения в userName, и маркер – в свойстве password. Это – полностью оправданное и ожидаемое использование.

    Как только учетные данные попадают в хранилище, они остаются дам для использования при следующих запусках приложения, до тех пор, пока вы не вызовите метод remove или пользователь явным образом не удалит их, с помощью команды Панель управления > Учетные записи пользователей и семейная безопасность > Диспетчер учетных данных (Control Panel > User Accounts and Family Safety >Credential Manager). На доверенном ПК (что требует входа в него с использованием учетной записи Microsoft), Windows автоматически и безопасно перемещает содержимое хранилища на другие устройства (это можно выключить с помощью команды Параметры ПК > Синхронизация параметров > Пароли (PC Settings > Sync Your Settings > Passwords)). Это помогает создать единую рабочую среду для вашего приложения, когда пользователь перемещается между устройствами .

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

  • findAllByResource Возвращает массив (вектор) объектов учетных данных по заданному идентификатору ресурса. Подобным образом можно получить имя пользователя и пароль, которые переместились с другого устройства, так как приложение сохранило учетные данные на другом компьютере с тем же самым идентификатором ресурса.
  • findAllByUserName Возвращает массив (вектор) объектов учетных данных по заданному имени пользователя. Это полезно, если вы знаете имя пользователя и хотите получить все учетные данные для множества ресурсов, к которым подключено приложение.
  • retrieve Возвращает единственный объект учетных данных по заданному ресурсу идентификатора и имени пользователя. Опять же, сочетанию имени пользователя и ресурса соответствует только один объект в хранилище.
  • retrieveAll Возвращает вектор всех учетных данных, имеющихся в хранилище для данного приложения. Ветор содержит копию состояния хранилища и не обновляется, если происходят последующие обновления учетных данных в хранилище.
  • Есть небольшое различие между методами findAll и retrieve в вышеприведенном списке. Метод retrieve предоставляет полностью заполненные объекты учетных данных. А методы findAll, с другой стороны, возвращают объекты, в которых свойство password не заполнено. Это предотвращает дешифрование пароля на основе потенциально большого набора учетных данных. Для того, чтобы заполнить это свойство для каждого отдельного объекта, вызовите метод PasswordCredential.retievePassword.

    Для дальнейшей демонстрации работы с хранилищем учетных данных – код здесь очень прост – обратитесь к примеру "Хранилище учетных данных" ( http://code.msdn.microsoft.com/windowsapps/PasswordVault-f01be74a). Он показывает варианты работы для одного пользователя/одного ресурса (Сценарий 1), одного пользователя/несколькоих ресурсов (Сценарий 2), нескольких пользователей/нескольких ресурсов (Сценарий 3), а так же – полную очистку хранилища (Сценарий 4).

    Брокер веб-проверки подлинности

    Хотя приложения могут принимать учетные данные пользовтеля и управлять ими собственными силами, поддерживая пользователей, возможно, с возможностью создания учетных записей для конкретных приложений или конкретных сервисов (обычно с помощью чудо-кнопки Параметры, как обсуждалось в Главе 2 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript", а так же в материале "Руководство и контрольный список для элементов управления входом" (http://msdn.microsoft.com/library/windows/apps/hh965453.aspx ), может возникнуть необходимость использовать учетную запись, которую пользователь уже создал посредством другого OAuth-поставщика, остобенно когда вы хотите использовать ресурсы этого поставщика. Вероятно, вы уже сталкивались с этим на многих веб-сайтах, куда можно войти через другой сайт, наподобие Facebook. Конечно, это обычно означает переход с исходного сайта на сайт поставщика – процесс, который отлично происходит в веб-браузере, но не столь привлекателен в контексте приложения!

    Для этой цели Windows предоставляет Брокера веб-проверки подлинности (Web Authentication Broker), который делает то же самое, не покидая контекст приложения. Приложение предоставляет URI для страницы проверки подлинности на внешнем сайте (необходимо использовать схему URI-схему https://, в противном случае вы получите ошибку, вызванную неподходящим параметров). Затем брокер создает новый хост-процесс для веб в его собственном контейнере приложения, в который и загружает указанную веб-страницу. Пользовательский интерфейс для этого процесса показан в виде находящегося поверх приложения диалогового окна, рис 8.2, для чего я использовал Сценарий 1 примера "Брокер веб-проверки подлинности" (http://code.msdn.microsoft.com/windowsapps/Web-Authentication-d0485122 ).

    (рис 8.2) Пример использования брокера веб-проверки подлинности со страницей входа в систему сервиса Facebook

    Примечание. Для того, чтобы запустить пример, вам понадобятся ID приложения для каждого из поставщиков аутентификации в различных сценариях. Для Facebook в Сценарии 1, посетите http://developers.facebook.com/setup и создайте App ID/API Key для тестового приложения.

    В случае с Facebook, процесс аутентификации включает в себя больше, чем просто проверка учетных данных пользователя. Кроме того, нужно получить различение на других возможности, которыми собирается пользоваться приложение (пользователь может независимо от приложения отменить их на сайте Facebook). В результате, процесс аутентификации может включать в себя переходы на дополнительные страницы, каждая из которых будет отображаться в брокере веб-проверки подлинности, как показано на рис 8.3. В данном случае идентификатор приложения, ProgrammingWin8_AuthTest, это тот, что я только что создал посредством страницы настроек разработчика Facebook для целей этой демонстрации.

    (рис 8.3) Дополнительные шаги аутентификации в Facebook внутри брокера веб-проверки подлинности

    В интерфейсе брокера веб-проверки пользователь может пройти через множество страниц сайта поставщика (обратите внимание на то, что кнопка Назад, около заголовка "Сonnecting to a service" (Подключение к сервису) полностью закрывает это окно). Но все это приводит к к вопросу: как брокер узнает, что аутентификация завершилась? Последний шаг в процессе аутентификации на правой части рис 8.3. – нажатие на кнопку Allow (Разрешить) , после чего обычно Facebook отображает страницу с информацией об успешном входе. В контексте приложения, однако, нам не нужно отображать подобную страницу – скорее нужно закрыть окно брокера и вернуться в приложение с результатом аутентификации. Более того, многие OAuth-поставщики даже не имеют подобной страницы. Что же нам делать?

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

    Как часть этого процесса, Facebook сохраняет информацию о различных разрешениях на собственном сервере для каждого конкретного пользователя, поэтому, если приложение снова запустит процесс аутентификации, пользователь не увидите тех же страниц, что показаны на рис 8.3. Пользователь может, конечно, управлять этими разрешениями, когда посещает страницу Facebook через веб-браузер, если пользователь удалит здесь информацию о приложении, то при повторном входе через приложение снова будут показаны те же страницы.

    В WinRT брокер представлен классом ). Аутентификация производится с помощью его методов authenticateAsync. Я написал здесь "методов", так как имеется два их варианта. Мы посмотрим на один из них здесь и вернемся ко всторому в следующем разделе, "Режим единого входа".

    Первый вариант метода authenticateAsync принимает три аргумента:

  • ) (скомбинированных с помощью побитового OR). Возможные значения: none (по умолчанию), silentMode (не отображается интерфейс), useTitle (возвращает в результатах заголовок окна веб-страницы), useHttpPost (возвращает в результатах тело страницы), и useCorporateNetwork (для вывода в контейнере приложения веб-страниц с возможностями Частные сети (клиент и сервер) (Private Networks (Client Server)), Корпоративная аутентификация (Enterprise Authentication), Общие сертификаты пользователей (Shared User Sertificates); кроме того, приложение должно объявить эти возможности).
  • requestUri URI (Windows.Foundation.Uri) для страницы аутентификации поставщика с параметрами, которые нужны сервису; повторюсь, здесь необходимо использовать схему URI https://.
  • callbackUri URI (Windows.Foundation.Uri) конечной страницы, отображаемой в процессе аутентификации у поставщика. Брокер использует этот адрес для определения момента закрытия собственного интерфейса .
  • Результат, передаваемый обработчику завершения ). Он содержит следующие свойства: ), которое может принимать значения success, userCancel, или errorHttp), responseData (строка, содержащая заголовок страницы и ее тело, если, соответственно, установлены опции useTitle и useHttpPost), и responseErrorDetail (номер ошибки HTTP).

    Вообще говоря, приложению особенно интересно содержимое responseData, так как здесь будет содержаться маркер или другие ключи, которые могут понадобиться ему позже. Посмотрим на это снова, в контексте Сценария 1 примера "Брокер веб-проверки подлинности" (http://code.msdn.microsoft.com/windowsapps/Web-Authentication-d0485122 ). Установим точку основа в обработчике завершения authenticateAsync (строка 59 или поблизости), и запустим пример, введем ID приложения, который был создан ранее и нажмем Launch (Запустить). (Обратите внимание на то, что параметр callbackUri установлен в https://www.facebook.com/connect/login_success.html, это страница, на которой завершается процесс аутентификации).

    В случае с Facebook, responseData содержит строку такого вида:

            https://www.facebook.com/connect/login_success.html#access_token=<token>
            expires_in=<timeout>
          

    Здесь в <token> Содержится куча алфавитно-цифровой абракадабры, <timeout>

  • это некоторый период, заданный Facebook. Если вы вызовете какое-нибудь API Facebook, что весьма вероятно, так как вы не случайно проходите аутентификацию через Facebook, <token>
  • это настоящее богатство, так как именно с его помощью вы аутентифицируете пользователя, когда выполняете вызовы к этому API.
  • Этот маркер доступа затем сохраняют в хранилище учетных данных для последующего использования, когда приложение будет перезапущено после приостановки или остановки. (В случае с Facebook, вам не нужно беспокоиться об истечении срока действия этого маркера, так как API обычно сообщает об этом как об ошибке и имеет встроенный процесс обновления маркера). Что-то похожее вам придется делать при работе с другими поставщиками аутентификация, обращаясь, конечно, к их документации, которая сообщит о том, что вы получите в ответе сервера и как использовать и/или обновлять ключи или маркеры при необходимости.

    В целом, ключевое преимущество веб-аутентификации это то, что пользователь никогда не предоставляет учетные данные приложению – пользователь передает их лишь гораздо более доверенному поставщику. С точки зрения приложения, так же, ему никогда не требуется управлять этими учетными данными, лишь токеном, который возвращает поставщик. По той же причине, при запуске брокера, который мы видели здесь, всегда будет отображаться страница входа с пустыми полями, независимо от флага Оставаться в системе (Keep Me Logged In), так как приложение не хранит подобных данных, и любые куки и состояния сессии находятся внутри окружения брокера и не сохраняются. Таким образом, если приложению нужно дать пользователю доступ к тому же сервису с другими учетными данными, ему достаточно запустить брокер, как ранее, и заменить токены или ключи, которые были сохранены при последнем сеансе аутентификации.

    Говоря о поставщиках, страница про OAuth в Википедии ( http://ru.wikipedia.org/wiki/OAuth) содержит перечисление существующих поставщиков аутентификации. Пример "Брокер веб-проверки подлинности", в свою очередь, показывает как работать с Facebook (Сценарий 1), Twitter (Сценарий 2), Flickr (Сценарий 3), и Google/Picasa (Сценарий 4), и так же предоставляет общий интерфейс для любых других сервисов (Сценарий 5).

    Полезно просмотреть эти разные сценарии, так как Facebook и Google используют протокол OAuth 2.0, requestUri для каждого выглядитдовольно простым (если исключить перенос слов:

    https://www.facebook.com/dialog/oauth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    scope-read_streamdisplay=popupresponse_type=token
    
    https://accounts.google.com/o/oauth2/auth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    response_type=codescope=http://picasaweb.google.com/data
    https://www.facebook.com/dialog/oauth?client_id=<client_id>
    redirect_uri=<redirectUri>
    
    scope-read_streamdisplay=popupresponse_type=token
          

    Здесь <client_id>и <redirectUri> заменяется на то, что задано приложением. Twitter иFlickr, в свою очередь, используют вместо этого протокол OAuth 1.0a, в итоге, требуется включать длинный маркер OAuth в аргумент requestUri для authenticateAsync. Подробности вы можете увидеть в коде примера.

    Совет. События брокера веб-проверки подлинности можно просмотреть окне Просмотр журналов событий (Event Viewer) в разделе Журналы приложений и служб > Microsoft > Windows > WebAuth> Operational (Application And Services Logs >Microsoft > Windows > WebAuth > Operational). Это может быть полезным для целей отладки, так как здесь можно увидеть данные, которые, в противном случае, скрыты за непрозрачным окружением брокера.

    Режим единого входа

    Все, касающееся хранилища учетных данных и брокера веб-проверки подлинности, отлично работает для минимизации того, как часто приложение донимает пользователя вопросами о вводе учетных данных. Когда речь идет об отдельном приложении, очень хороша возможность один раз запросить учетные данные и не запрашивать их снова до тех пор, пока пользователь явным образом не выйдет из системы. Но как насчет нескольких приложений. Представьте себе, что вы установили несколько десятков или сотен приложений из Магазина Windows, использующих внешних поставщиков аутентификации. Это может означать, что вы будете вводить учетные данные для входа в аккаунты Facebook, Twitter, Google, LinkedIn, Tumblr, Yahoo, или Yammer в каждое приложение, которое их использует. Очевидно, в каждом отдельном приложении это нужно будет лишь раз, но общий эффект оказывается утомляющим и надоедливым!

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

    Концепция режима единого входа (SSO) в этом и заключается: проверка подлинности пользователя в одном приложении (или во всей системе, в случае с учетной записью Microsoft) приводит к возможности входа в другие приложения, которые используют того же поставщика. В то же время, каждое приложение обычно должно получить собственные ключи доступа или маркеры, так как их не следует делать общими для разных приложений. В итоге весь фокус заключается в том, чтобы эффективно произвести тот же процесс аутентификации, который мы видели, только сделать его, не показывая пользовательский интерфейс до тех пор, пока это действительно не будет нужно.

    Это можно реализовать с помощью брокера веб-проверки подлинности с помощью одного из вариантов authenticateAsync, который принимает лишь аргументы options и requestUri. В данном случае options часто устанавливается в WebAuthenticationOptions.silentMode для того, чтобы предотвратить показ интерфейса рокера (но это не обязательно).

    Для того, чтобы режим silentMode заработал, брокеру все еще нужно узнать, когда завершится процесс проверки подлинности. Поэтому, какой же callbackUri ему использовать для сравнения и как поставщик узнает то, что ему нужно? Это напоминает ситуацию, когда брокер находится в системе, всегда скрытый, в то время, Как поставщик терпеливо ожидает ввода данных на веб-страницу, которая полностью невидима! Что, на самом деле происходит, это то, что authenticateAsync ожидает, когда поставщик перейдет по особому callbackUri , которое выглядит как ms-app://<app_package> /<secret_sauce>, после чего результат ответа поставщика будет передан в виде асинхронного результата.

    Конечно, данный URI неичего не значит для поставщика …если только его не оповестили об этом заранее и он не ожидает появления подобного URI в своей среде.

    Это сообщает нам о том факте, что режим единого входа работает только если провайдер имеет средства (API или что-то вроде того), посредством которого приложение может сообщить о своих намерениях. Для того, чтобы это понять, рассмотрим полный рабочий процесс "тихой" аутентификации:

  • Приложение, которое желает использовать режим единого входа, подписывается, с помощью одного из двух средств, на получение собственного URI ms-app://, который так же называется SID URI. Во-первых, это возможно с помощью вызова статического метода WebAuthenticationBroker.getCurrentApplicationCallbackUri. Этот вызов возвращает объект Windows.Foundation.Uri, строковое свойство которого absoluteUri, это как раз то, что вам нужно. Во-вторых, это можно реализовать на странице Магазина Windows Информационная панель > Управление облачными службами > Дополнительные функции > Проверка подлинности приложения (Dashboard > Manage Your Cloud Services > Advanced Features > Application Authentication), где вы сможете увидеть строку, выглядящую примерно так: ms-app://s-1-15-2-477157379-2961032073-432767880-3229792171-202870256-1369967874-2241987394/.
  • Если нужно, приложение затем вызывает API поставщика для регистрации этого SID URI (обычно у поставщика есть страница для указания приложения, где вводят эти данные).
  • При создании аргументов requestUri для authenticateAsync, приложение добавляет свой SID URI в качестве значения для параметра redirect_uri=.
  • Приложение вызывает authenticateAsync с опцией silentMode.
  • Когда поставщик обработает параметры requestUri, он проверяет, зарегистрировано ли значение redirect_uri, и, если это не так, отвечает сообщением об ошибке.
  • Производя проверку приложения, поставщик затем, не задавая вопросов (если возможно) производит проверку подлинности и переходит по redirect_uri, не забыв включить маркеры и ключи доступа в данные ответа.
  • Брокер веб-проверки пользователя обнаруживает этот переход и сравнивает его адрес со своим callbackUri. Обнаружив совпадение, брокер может завершить асинхронную операцию и предоставить приложению данные ответа поставщика.
  • Опять же, у поставщика должны быть средства, с помощью которых разработчик или приложение могут зарегистрировать SID URI, он должен проверить SID URI, когда оно оказывается в запросе на проверку подлинности, и должен выдать подходящий ответ на эту страницу, когда проверка подлинности завершена. Таким образом, поставщик или приложение ответственны за регистрацию SID URI и за включение его в requestUri. (Ух ты, сколько же URI!)

    При всем этом, все еще возможно, что проверка подлинности может не удастся по каким-то другим причинам. Например, если пользователь не установил полномочия приложения для этого (как в случае с Facebook), "тихая" проверка подлинности не возможна. Таким образом, приложение пытается использовать режим единого входа, вызывает сначала authenticateAsync соответствующего вида, а если это не удается, пытается вызвать его более длинный вариант (с показом пользовательского интерфейса), как описано в предыдущем разделе.

    Режим единого входа в службу Live Connect

    Так как различные службы Microsoft, такие, как Hotmail, являются поставщиками OAuth, возможно использовать брокер веб-проверки подлинности с учетной записью Microsoft (с такой, как учетные записи Hotmail, Live, и MSN). (У меня все еще есть учетная запись электронной почты @msn.com, которую я получил в 1996!). Подробности можно найти на странице "OAuth 2.0" ( http://msdn.microsoft.com/library/live/hh243647.aspx) в Центре разработчиков Live Connect.

    Тем не менее, учетные записи Live Connect находятся в более привилегированном положении, так как их можно использовать для входа в Windows, или подключить к доменной учетной записи для той же цели. Многие из встроенных приложений, такие, как Mail (Почта), Calendar (Календарь), SkyDrive, People (Люди) и Магазин Windows, работают с той же учетной записью. Таким образом, это то, чем, возможно, захотят воспользоваться многие другие приложения, так как подобная аутентификация дает доступ к тем же данным служб Live, с которыми работают встроенные приложения. API Live Services выглядит как WL.login, он доступен при Live SDK и добавляет в проект соответствующие ссылки. Для того, чтобы начать работу, посетите страницу документации по Live Connect (http://msdn.microsoft.com/ru-ru/library/live/ff621314.aspx ) и почитайте следующие материалы:

  • Live Connect, домашняя страница (http://msdn.microsoft.com/library/windows/apps/hh770845.aspx )
  • Центр разработчиков Live Connect (http://msdn.microsoft.com/library/live/hh826551.aspx )
  • Руководство по единому входу и подключенным учетным записям ( http://msdn.microsoft.com/library/windows/apps/jj193591.aspx)
  • Руководство по взаимодействию с пользователем при входе в учетную запись Майкрософт (http://msdn.microsoft.com/library/windows/apps/hh968443.aspx )
  • Единый вход с учетной записью Майкрософт (http://msdn.microsoft.com/library/windows/apps/hh465097.aspx )
  • Краткое руководство: персонализация приложения (http://msdn.microsoft.com/library/windows/apps/hh920269.aspx )
  • Пример "Авторизация с учетной записью Microsoft" (http://code.msdn.microsoft.com/windowsapps/Windows-account-authorizati-7c95e284 )
  • Материалы блога для разработчиков приложения для Windows 8 "Внедрение функций единого входа и SkyDrive в приложения для Windows 8 с помощью Live SDK" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/03/22/skydrive-windows-8-live-sdk.aspx ) и "Рекомендации по добавлению функции единого входа в приложения с помощью Live SDK" ( http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/07/02/live-sdk.aspx).
  • Вы можете видеть, что работа со службами Live – весьма обширная тема, поэтому я оставляю ее вышеприведенным ресурсам. Хочу упомянуть один из ключевых моментов. Пользователь может войти в Windows с использованием доменной учетной записи, которая не подключена к учетной записи Microsoft в разделе Параметры ПК > Пользователи (PC Settings > Users). В подобном случае первый вызов WL.login, исходящий от любого приложения, отобразит диалоговое окно для входа в учетную запись Microsoft, как показано на рис 8.4. Как только пользователь введет здесь учетные данные, осуществится вход и во все остальные приложения, которые используют учетную запись Microsoft.

    (рис 8.4) Диалоговое окно входа в учетную запись Microsoft

    Профиль пользователя (и изображение экрана блокировки)

    Любой разговор об учетных данные пользователя вызывает вопрос о доступе к дополнительной информации пользователя. То, что доступно приложениям для Магазина Windows, предоставляется с помощью API Windows.System.UserProfile (http://msdn.microsoft.com/library/windows/apps/windows.system.userprofile.aspx ), где мы можем найти классы, относящиеся к предмету нашего интереса.

    Первый – это класс ) для того, чтобы увидеть демонстрацию этого.

    >Второй – это объект ), к которому мы вернемся к Главе 6.

    Третий – это класс ), возможности которого отражены на странице Параметры ПК > Персонализация > Аватар (PC Settings > Personalize > Account picture):

  • Имя пользователя (User name) Если свойство nameAccessAllowed установлено в true, приложение может вызывать методы getDisplayNameAsync, getFirstNameAsync, и getLastNameAsync, каждый из которых предоставляет строку в обработчик завершения. Если nameAccessAllowed установлено в false, эти методы выполняются, до завершения, но возвращают пустой результат. Кроме того, обратите внимание на то, что получение имени (first name) и фамилии (last name) доступно лишь из учетной записи Microsoft
  • Изображение пользователя (User picture) Его можно получить, воспользовавшись методом ): smallImage, largeImage, и video.
  • Если свойство ): success, failure, changeDisabled (accountPictureChangeEnabled установлено в false), largeOrDynamicError (изображение слишком велико), fileSizeError (файл слишком велик), или videoFrameSizeError (размер кадра видео слишком велик),
  • Событие accountpicturechanged вызывается, когда изображение (или изображения) пользователя изменяется. Помните о том, что так как это – событие, исходящие из WinRT, вам следует вызвать removeEventListener, если вы не намерены прослушивать это событие во время работы приложения.
  • Демонстрацию этих возможностей можно найти в примере "Имя пользователя и изображение учетной записи" (http://code.msdn.microsoft.com/windowsapps/Account-picture-name-sample-912baff1 ). Сценарий 1 получает отображаемое имя, Сценарий 2 получает имя и фамилию пользователя (если они доступны), Сценарий 3 получает изображение учетной записи и видео, Сценарий 4 позволяет изменить изображения и видео, и прослушивать событие изменения изображений.

    Совет. Для того, чтобы получить изображение профиля из Live Connect, можно воспользоваться следующим вызовом API: https://apis.live.net/v5.0/me/picture?access_token=<ACCESS_TOKEN> Кроме того, этот пример показывает объявление Поставщик изображений для учетных записей(Account Picture Provider), благодаря чему приложение отображается в окне Параметры ПК > Персонализация, в разделе Приложения для создания аватара (Create an Account Picture):

    В данном случае приложение-пример не предоставляет изображение напрямую, но активируется со Сценарием 4. Реальное приложение, такое, как Camera (Камера), которая есть в Параметрах ПК по умолчанию, автоматически задаст изображение учетной записи, когда оно будет получено с помощью его интерфейса. Откуда приложение знает, как это сделать? Ответ находится в специальной схеме URI, посредством которой активируется приложение. Таким образом, если вы сделали объявление Поставщик изображений для учетных записей(Account Picture Provider) в манифесте, приложение будет активировано с видом активации protocol (смотрите Главу 1), где схема URI начинается с ms-accountpictureprovider. Вы можете увидеть, как обрабатывается такая активация в файле js/default.js:

    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.protocol) {
    // Проверяет, совпадает ли protocol со схемой "ms-accountpictureprovider"
    if (eventObject.detail.uri.schemeName === "ms-accountpictureprovider") {
    // Приложение было активировано с помощью команды задания аватара в разделе Персонализация в Параметрах ПК.
    // Здесь можно выполнить действия по предоставлению пользователю интерфейса для
    // выбора изображения учетной записи.
    }
          

    Возвращаясь к классу UserInformation, можно сказать, что так же он предоставляет немного больше подробностей для доменных учетных записей, предполагая, что у приложения, в манифесте, объявлена возможность Корпоративная аутентификация (Enterprise Authentication):

  • getDomainNameAsync предоставляет полностью определенное доменное имя пользователя в виде строки, в форме
    <domain>
      \<user>
       где <domain>

    Это полное имя контроллера домена, как, например, mydomain.corp.ourcompany.com.

  • getPrincipalNameAsync Предоставляет имя субъекта в виде строки. В применении к Active Directory, это имя для входа, в интернет-стиле (известное как имя субъекта-пользователя (user principal name), или UPN), которое короче и проще, чем доменное имя, объединяя имя для входа в систему и адрес электронного почтового ящика. Обычно – это адрес электонной почты наподобие user@ourcompany.com.
  • ).
  • Использование этих методов показано в примере "Доменное имя пользователя" (http://code.msdn.microsoft.com/windowsapps/User-domain-name-sample-85ce3e49 ).

    Шифрование, расшифровка, защита данных и сертификаты

    Авторизация и учетные записи – это темы, связанные с безопасностью, поэтому хорошо будет завершить этот раздел кратким разбором других API, которые находятся в пространстве имен Windows.Security, одно из которых, брокер веб-проверки пользователей, мы уже рассматривали.

    Первое - это ). Здесь вы можете найти класс CryptographicBuffer, который позволяет кодировкить и декодировать строки в шестнадцатеричном формате и в формате base64 (UTF-8 или UTF-16), предоставляет набор случайных числе и байтовый массив, полный таких чисел. Обратитесь к Сценарию 1 примера "Криптография в WinRT" (http://code.msdn.microsoft.com/windowsapps/CryptoWinRT-54ff3d9f ) чтобы увидеть демонстрацию его применения, а так же, к Сценариям 2 и 3 примера "Брокер веб-проверки подлинности". Кодировка base64 WinRT полностью совместима с функциями JavaScript atob и btoa.

    Далее, это ), который применим к шифрованию и расшифровке с использованием различных алгоритмов. Смотрите материал "Шифрование" ( http://msdn.microsoft.com/library/windows/apps/hh464976.aspx), Сценарии 2 – 8 примера "Криптография в WinRT", и, снова Сценарии 2 и 3 примера "Брокер веб-проверки подлинности"

    Третье – ), единственный класс которого, ) и к сценариям 9 и 10 примера "Криптография в WinRT".

    Четвертое - ) предоставляет несколько классов, с помощью которых можно создавать запросы сертификатов и устанавливать отклики сертификатов. Обратитесь к материалу "Работа с сертификатами" (http://msdn.microsoft.com/library/windows/apps/hh465044.aspx ) и к примеру "Работа с сертификатом" (http://code.msdn.microsoft.com/windowsapps/Certificate-Enrollment-SDK-7ecf4976 ) для того, чтобы узнать подробности.

    И, наконец, полезно по меньшей мере упомянуть API из ), имеется пример "EAS-политики для почтового клиента" (http://code.msdn.microsoft.com/windowsapps/Web-authentication-for-b9b8ed1a ). Думаю, вы знаете, зачем вам это может понадобиться.

    Вернуться к учебному плану