Статьи

Образец Windows Azure Mobile Services «Арендуй дом», часть 3: проверка подлинности

В прошлый раз мы исследовали пользовательский интерфейс и серверный скрипт для нашего приложения для списков квартир. Сегодня мы увидим, как добавить аутентификацию в микс и ограничить определенные операции только для аутентифицированных пользователей. Это особенно важно в приложении Rent a Home, потому что вы не хотите, чтобы анонимные пользователи удаляли и обновляли списки квартир! На самом деле вы, вероятно, захотите, чтобы только пользователь, создавший объявление о квартире, имел право обновить или удалить его.

ПРИМЕЧАНИЕ. Службы Windows Azure Mobile по умолчанию настроены так, чтобы любой пользователь с URL-адресом приложения и ключом приложения мог выполнять операции создания, извлечения, обновления и удаления любых таблиц, принадлежащих этой службе. Поскольку ключ приложения распространяется на клиентские устройства, это, очевидно, очень плохая идея для производственного приложения — любой может извлечь ключ приложения из вашего приложения и выполнить произвольные изменения ваших данных. Поэтому в рабочей конфигурации крайне важно, чтобы вы ограничивали доступ к своим данным только для аутентифицированных пользователей. Может показаться целесообразным разрешить чтение данных любому, у кого есть ключ приложения, но операции создания / обновления / удаления должны требовать аутентификации.

Службы Windows Azure Mobile в настоящее время поддерживают проверку подлинности с помощью четырех поставщиков проверки подлинности: учетной записи Microsoft (Live Connect), Google, Twitter и Facebook. (Приложение Rent a Home поддерживает только аутентификацию Twitter, но было бы тривиально добавить поддержку и других провайдеров.)

Прежде чем вы сможете выполнить аутентификацию с помощью Twitter, вам нужно создать приложение Twitter (для этого посетите сайт dev.twitter.com ) и указать его ключ и секретный ключ на портале Windows Azure. Затем вы можете немедленно начать делать запросы на аутентификацию от поддерживаемых клиентов:

Android

mobileService.login(MobileServiceAuthenticationProvider.Twitter,
  new UserAuthenticationCallback() {
    public void onCompleted(MobileServiceUser user,
                            Exception exception,
                            ServiceFilterResponse response) {
      if (exception != null) {
        displayError(exception);
      } else {
        setTitle("Welcome! User id: " + user.getUserId());
      }
    }
  });

ПРИМЕЧАНИЕ. Идентификатор пользователя не является именем пользователя; это непрозрачное число, которое пользователи будут удивлены, увидев. Позже в этом посте мы увидим, как получить имя пользователя из идентификатора пользователя.

IOS

UIViewController *vc =
  [self.client loginViewControllerWithProvider:@"twitter"
               completion:^(MSUser *user, NSError *error) {
    if (error) {
      NSLog(@"Authentication Error: %@", error);
      //error.code == -1503 means user cancelled the dialog
    } else {
      //Authentication was successful, use self.client.currentUser
      //to read information about the user
    }
    [self dismissViewControllerAnimated:YES completion:nil];
  }];
[self presentViewController:vc animated:YES completion:nil];

Windows Phone и Windows 8

var user = await App.MobileService.LoginAsync(
                MobileServiceAuthenticationProvider.Twitter);
btnLogin.Visibility = Visibility.Collapsed;
txtLogin.Visibility = Visibility.Visible;
txtLogin.Text = "Logged in using Twitter";

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

function insert(item, user, request) {
  if (user) {
    item.user = user.userId;
  }
  //The rest of the code omitted for brevity
}

Благодаря динамической схеме, нет необходимости предварительно декларировать  user недвижимость в списках квартир. Этого свойства на самом деле достаточно, чтобы защитить списки квартир от изменения «неправильным» пользователем. Например, это может быть наш скрипт удаления на  apartment столе:

function delete(item, user, request) {
  if (!user || user.userId !== item.userId) {
    request.respond(403, 'Only the user that created the ' +
                         'apartment listing may delete it.');
  }
  request.execute();
}

Как вы видели в пользовательском интерфейсе приложения, было бы также полезно отображать информацию о владельце другим пользователям (это послужило бы основой для того, чтобы помочь пользователям связаться с владельцем квартиры для заключения сделки). Поскольку идентификатор пользователя не является понятным для пользователя именем пользователя, мы должны использовать API, специфичный для службы (в данном случае, Twitter), для получения имени пользователя. Это делается в скрипте вставки  apartment таблицы, например так:

item.username = '<Unknown User>';
var identities = user ? user.getIdentities() : null;
if (identities && identities.twitter) {
  var id = user.userId.substring(userId.indexOf(':') + 1);
  var url = 'https://api.twitter.com/1/users/show.json?user_id='
            + id;
  reqModule(url, function (err, resp, body) {
    if (err || resp.statusCode !== 200) {
      request.respond(500, body);
    } else {
      try {
        item.username = JSON.parse(body).name;
        //Continue processing as usual
      } catch (ex) {
        request.respond(500, ex);
      }
    }
  });
}

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

Резюме
На данный момент мы добавили поддержку аутентификации в наше приложение. Пользователи могут войти в систему через Твиттер, а их списки квартир связаны с их личностью в Твиттере. Мы также ограничили доступ, чтобы только аутентифицированные пользователи могли создавать новые списки квартир, и только создавшему пользователю разрешается обновлять или удалять списки квартир. Еще одна вещь, которую было бы «приятно иметь», — это поддержка пользовательских идентификаторов, то есть пользовательских учетных данных имени пользователя и пароля для вашей службы.  Джош Твист из команды мобильных сервисов объясняет,  что будет необходимо для обеспечения такой поддержки на стороне вашего приложения.

Наконец, есть одна довольно раздражающая деталь о текущей реализации: она требует, чтобы пользователь входил в систему каждый раз, когда открывал приложение. Хотя бэкэнд не требует повторной аутентификации, клиентский SDK в настоящее время не имеет автоматического способа сохранения токена аутентификации в каком-либо безопасном хранилище. Однако это не должно мешать вам сохранять маркер аутентификации самостоятельно и передавать его соответствующему  login методу клиента Mobile Service. Для полного примера, см  . Пост Джоша Твиста .

В следующей части мы рассмотрим, как настроить push-уведомления на всех четырех платформах и как доставлять push-уведомления зарегистрированным клиентам.


Я публикую короткие ссылки и обновления в Твиттере, а также в этом блоге. Вы можете следовать за мной:  @goldshtn