Как использовать пакет ASP.NET Framework для мобильных приложений Azure

В этом разделе показано, как использовать пакет SDK для внутреннего сервера .NET в основных сценариях применения мобильных приложений службы приложений Azure. Пакет SDK для мобильных приложений Azure помогает работать с мобильными клиентами из своего приложения ASP.NET.

Предупреждение

В этой статье рассматриваются сведения о версии библиотеки версии 4.2.0, которая заменена библиотекой версии 5.0.0. Последние сведения см. в статье о последней версии

Создание серверной части ASP.NET Framework для мобильных приложений Azure

Приложение ASP.NET Framework можно создать с помощью Visual Studio 2019.

  • Выберите шаблон Веб-приложение ASP.NET (.NET Framework). Если вы не можете найти этот шаблон, выберите C#, Все платформы и Интернет.
  • После выбора имени и расположения для приложения выберите шаблон проекта Веб-API. Будет установлена необходимая коллекция базовых служб для приложения.

Скачивание и инициализация пакета SDK

Пакет SDK доступен на NuGet.org и предоставляет базовые функции, необходимые для начала работы с мобильными приложениями Azure. Чтобы установить пакет, выполните следующие действия:

  1. Щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet….
  2. На вкладке Обзор введите Microsoft.Azure.Mobile.Server в поле поиска и нажмите клавишу ВВОД.
  3. Выберите пакет Microsoft.Azure.Mobile.Server.Quickstart.
  4. Щелкните Установить.
  5. Следуйте указаниям, чтобы завершить установку.

Повторите эту процедуру, чтобы также установить Microsoft.Owin.Host.SystemWeb.

Примечание.

Не обновляйте пакеты, используемые в качестве зависимостей, например, Newtonsoft.JSON или System.IdentityModel.Jwt. API этих пакетов во многих случаях изменились и теперь несовместимы с мобильными приложениями Azure для ASP.NET Framework.

Инициализация проекта сервера

Инициализировать проект сервера мобильных приложений Azure можно так же, как и другие проекты ASP.NET Framework — включив класс запуска OWIN. Чтобы добавить класс запуска OWIN, выполните следующие действия:

  1. Щелкните проект правой кнопкой мыши и выберите команду Добавить>Новый элемент.

  2. Выберите Интернет>Общие, а затем выберите шаблон класса запуска OWIN.

  3. Введите имя Startup.cs в качестве имени запуска.

  4. Файл Startup.cs должен включать код, похожий на следующий:

    using Microsoft.Azure.Mobile.Server.Config;
    using Microsoft.Owin;
    using Owin;
    using System.Web.Http;
    
    [assembly: OwinStartup(typeof(WebApplication1.Startup))]
    namespace WebApplication1
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                HttpConfiguration config = new HttpConfiguration();
                new MobileAppConfiguration()
                    // no added features
                    .ApplyTo(config);
                app.UseWebApi(config);
            }
        }
    }
    

    Пространство имен OwinStartup и имя класса будут отличаться от указанных в зависимости от проекта. В частности, следует заменить содержимое метода Configuration() и соответствующим образом изменить директивы using.

Чтобы включить отдельные функции, перед вызовом ApplyTo необходимо вызвать методы расширения для объекта MobileAppConfiguration. Например, следующий код добавляет во время инициализации маршруты по умолчанию для всех контроллеров API, имеющих атрибут [MobileAppController] :

new MobileAppConfiguration()
    .MapApiControllers()
    .ApplyTo(config);

Следующая конфигурация считается "нормальным" использованием и позволяет контроллерам таблиц и API, использующим Entity Framework, обращаться к службе SQL.

new MobileAppConfiguration()
    .AddMobileAppHomeController()
    .MapApiControllers()
    .AddTables(
        new MobileAppTableConfiguration()
            .MapTableControllers()
            .AddEntityFramework()
    )
    .MapLegacyCrossDomainController()
    .ApplyTo(config);

Используются следующие методы расширения:

  • AddMobileAppHomeController() предоставляет домашнюю страницу мобильных приложений Azure по умолчанию.
  • MapApiControllers() предоставляет возможности настраиваемого интерфейса API для контроллеров веб-API с атрибутом [MobileAppController].
  • AddTables() обеспечивает сопоставление конечных точек /tables контроллерами таблиц.
  • AddTablesWithEntityFramework() — это сокращение для сопоставления конечных точек /tables с помощью контроллеров на основе Entity Framework.
  • MapLegacyCrossDomainController() предоставляет стандартные заголовки CORS для локальной разработки.

Расширения пакета SDK

Следующие пакеты расширений на основе NuGet предоставляют различные возможности мобильных устройств, которые может использовать ваше приложение. Вы можете включить расширения во время инициализации с помощью объекта MobileAppConfiguration .

  • Microsoft.Azure.Mobile.Server.Quickstart поддерживает базовую настройку мобильных приложений. Чтобы добавить его в конфигурацию, во время инициализации необходимо вызвать метод расширения UseDefaultConfiguration. Это расширение включает в себя следующие расширения: пакеты Notifications, Authentication, Entity, Tables, Crossdomain и Home.
  • Microsoft.Azure.Mobile.Server.Home реализует стандартную страницу «Это мобильное приложение запущено и работает» для корневого каталога веб-сайта. Чтобы добавить его в конфигурацию, вызовите метод расширения AddMobileAppHomeController .
  • Microsoft.Azure.Mobile.Server.Tables содержит классы для работы с данными и настраивает конвейер данных. Чтобы добавить его в конфигурацию, вызовите метод расширения AddTables .
  • Microsoft.Azure.Mobile.Server.Entity позволяет платформе Entity Framework получать доступ к данным в базе данных SQL. Чтобы добавить его в конфигурацию, вызовите метод расширения AddTablesWithEntityFramework .
  • Microsoft.Azure.Mobile.Server.Authentication включает функцию проверки подлинности и настраивает ПО промежуточного слоя OWIN, используемое для проверки токенов. Чтобы добавить его в конфигурацию, вызовите методы расширения AddAppServiceAuthentication и IAppBuilder.UseAppServiceAuthentication.
  • Microsoft.Azure.Mobile.Server.Notifications включает push-уведомления и определяет их конечную точку регистрации. Чтобы добавить его в конфигурацию, вызовите метод расширения AddPushNotifications .
  • Microsoft.Azure.Mobile.Server.CrossDomain создает контроллер, который передает устаревшим веб-браузерам данные из вашего мобильного приложения. Чтобы добавить его в конфигурацию, вызовите метод расширения MapLegacyCrossDomainController .
  • Microsoft.Azure.Mobile.Server.Login предоставляет статический метод AppServiceLoginHandler.CreateToken(), используемый в сценариях настраиваемой проверки подлинности.

Публикация серверного проекта

В этом разделе показано, как опубликовать серверный проект .NET из Visual Studio. Существуют и другие методы, с помощью которых можно опубликовать приложение. Дополнительные сведения см. в документации по службе приложений Azure.

  1. В Visual Studio выполните повторную сборку проекта, чтобы восстановить пакеты NuGet.
  2. В Обозревателе решений щелкните проект правой кнопкой мыши и выберите Опубликовать.
  3. Если вы еще не публиковали этот проект, будет настроена публикация.
    • Выберите Azure в качестве целевой платформы.
    • Выберите службу приложений Azure (Windows) в качестве конкретной целевой платформы.
    • Выберите экземпляр службы приложений, в который нужно выполнить развертывание. Если у вас его нет, создайте его с помощью +.
    • Нажмите кнопку Готово.
  4. Если вы не привязывали базу данных SQL, нажмите кнопку Настроить рядом с базой данных SQL.
    • Выберите База данных SQL Azure.
    • Выберите свою базу данных. Если у вас нет базы данных или вы хотите использовать другую базу данных, нажмите +, чтобы создать новую базу данных и сервер.
    • Введите MS_TableConnectionString в качестве имени строки подключения к базе данных. Укажите имя пользователя и пароль в указанных полях.
    • Нажмите кнопку Готово.
  5. Щелкните Опубликовать.

Публикация в Azure занимает некоторое время. Дополнительные сведения см. в документации по Visual Studio.

Определение контроллера таблиц

Определите контроллер таблиц, чтобы предоставить доступ к таблице SQL мобильным клиентам. Настройка контроллера таблиц состоит из трех шагов.

  1. Создание класса объекта передачи данных.
  2. Настройка ссылки на таблицу в мобильном классе DbContext.
  3. Создание контроллера таблиц.

Объект передачи данных — это обычный объект C#, наследуемый от EntityData. Например:

public class TodoItem : EntityData
{
    public string Text { get; set; }
    public bool Complete {get; set;}
}

Объект передачи данных используется для определения таблиц в Базе данных SQL. Чтобы создать запись в базе данных, добавьте свойство DbSet<> в используемый объект DbContext:

public class MobileServiceContext : DbContext
{
    private const string connectionStringName = "Name=MS_TableConnectionString";

    public MobileServiceContext() : base(connectionStringName)
    {

    }

    public DbSet<TodoItem> TodoItems { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(
            new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
                "ServiceColumnTable", (property, attributes) => attributes.Single().ColumnType.ToString()));
    }
}

Наконец, создайте контроллер:

  1. Щелкните правой кнопкой мыши папку Controllers.

  2. Выберите Веб-API>Контроллер веб-API 2 — пустой.

  3. Введите имя контроллера.

  4. Замените содержимое файла нового контроллера приведенным ниже кодом:

    public class TodoItemController : TableController<TodoItem>
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            ZUMOAPPNAMEContext context = new ZUMOAPPNAMEContext();
            DomainManager = new EntityDomainManager<TodoItem>(context, Request);
        }
    
        // GET tables/TodoItem
        public IQueryable<TodoItem> GetAllTodoItems()
        {
            return Query();
        }
    
        // GET tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public SingleResult<TodoItem> GetTodoItem(string id)
        {
            return Lookup(id);
        }
    
        // PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
        {
            return UpdateAsync(id, patch);
        }
    
        // POST tables/TodoItem
        public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
        {
            TodoItem current = await InsertAsync(item);
            return CreatedAtRoute("Tables", new { id = current.Id }, current);
        }
    
        // DELETE tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task DeleteTodoItem(string id)
        {
            return DeleteAsync(id);
        }
    }
    

Изменение размера постраничного представления таблиц

По умолчанию мобильные приложения Azure выдают по 50 записей на запрос. Разбивка на страницы гарантирует, что клиент не связывает ни поток пользовательского интерфейса, ни сервер надолго, обеспечивая таким образом удобство работы пользователей. Чтобы изменить размер постраничного представления таблиц, увеличьте допустимый размер запроса на серверной стороне и размер страниц на стороне клиента. Допустимый размер запроса на серверной стороне настраивается с помощью атрибута EnableQuery.

[EnableQuery(PageSize = 500)]

Значение параметра PageSize должно быть больше или равно размеру, запрошенному клиентом. Сведения об изменении размера страницы для изменения клиента см. в методических указаниях по соответствующему клиенту.

Определение настраиваемого контроллера API

Настраиваемый контроллер API обеспечивает большинство базовых функций для серверной части мобильного приложения, предоставляя конечную точку. Вы можете зарегистрировать контроллер API для мобильных приложений с помощью атрибута [MobileAppController]. Атрибут MobileAppController регистрирует маршрут, настраивает сериализатор JSON мобильных приложений, а также включает проверку версии клиента.

Содержимое файла настраиваемого контроллера API приведено ниже:

[MobileAppController]
public class CustomAPIController : ApiController
{
    // Content here
}

После настройки с помощью атрибута MobileAppController можно определить настраиваемый API так же, как любой другой веб-API.

Использование аутентификации

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

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

Вы можете добавить проверку подлинности в серверный проект, унаследовав от объекта MobileAppConfiguration и настроив ПО промежуточного слоя OWIN.

  1. В Visual Studio установите пакет Microsoft.Azure.Mobile.Server.Authentication .

  2. В файле проекта Startup.cs добавьте следующую строку кода в начало метода Configuration:

    app.UseAppServiceAuthentication(config);
    

    Этот компонент ПО промежуточного слоя OWIN проверяет маркеры, выданные соответствующим шлюзом службы приложений.

  3. Добавьте атрибут [Authorize] во все контроллеры и методы, в которых нужна проверка подлинности.

Использование настраиваемой проверки подлинности для приложения

Важно!

Чтобы включить настраиваемую аутентификацию, необходимо сперва включить на портале Azure проверку подлинности службы приложений без выбора поставщика вашей службы приложений. Это позволит включить переменную среды WEBSITE_AUTH_SIGNING_KEY при размещении.

Если вы не хотите использовать один из поставщиков проверки подлинности и авторизации службы приложений, можно реализовать свою собственную систему входа. Установите пакет Microsoft.Azure.Mobile.Server.Login , чтобы упростить создание маркеров проверки подлинности. Предоставьте свой собственный код для проверки учетных данных пользователя. Например, можно выполнять проверку с помощью дополненных случайными данными и хэшированных паролей в базе данных. В следующем примере за эти проверки отвечает метод isValidAssertion() (определенный в другом месте).

Пользовательская проверка подлинности осуществляется путем создания ApiController и использования действий register и login. Для сбора данных пользователя клиент должен использовать настраиваемый пользовательский интерфейс. Затем эти данные отправляются в API с помощью стандартного вызова HTTP POST. После проверки утверждения сервером выпускается маркер с помощью метода AppServiceLoginHandler.CreateToken() . В ApiController нельзя использовать атрибут [MobileAppController].

Пример действия login :

public IHttpActionResult Post([FromBody] JObject assertion)
{
    if (isValidAssertion(assertion)) // user-defined function, checks against a database
    {
        JwtSecurityToken token = AppServiceLoginHandler.CreateToken(new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, assertion["username"]) },
            mySigningKey,
            myAppURL,
            myAppURL,
            TimeSpan.FromHours(24) );
        return Ok(new LoginResult()
        {
            AuthenticationToken = token.RawData,
            User = new LoginResultUser() { UserId = userName.ToString() }
        });
    }
    else // user assertion was not valid
    {
        return this.Request.CreateUnauthorizedResponse();
    }
}

В предыдущем примере LoginResult и LoginResultUser — это сериализуемые объекты, содержащие необходимые свойства. Клиент ожидает возвращения ответов входа в виде объектов JSON в следующем формате.

{
    "authenticationToken": "<token>",
    "user": {
        "userId": "<userId>"
    }
}

Метод AppServiceLoginHandler.CreateToken() включает в себя параметры audience и issuer. Для обоих этих параметров обычно устанавливаются значения, равные URL-адресу корня приложения, с помощью схемы HTTPS. Точно так же для параметра secretKey нужно задать значение ключа подписывания приложения. Не распространяйте ключ подписывания в клиенте, так как он может быть использован для создания ключей и олицетворения пользователей. Если приложение размещено в службе приложений, этот ключ подписывания можно получить из переменной среды WEBSITE_AUTH_SIGNING_KEY. Если это необходимо для отладки в локальной среде, можно получить ключ и сохранить его как параметр приложения, выполнив инструкции из раздела Локальная отладка с проверкой подлинности .

Выданный маркер может содержать другие утверждения и иметь другую дату окончания срока действия. Выданный маркер должен содержать по крайней мере утверждение субъекта (sub).

Чтобы обеспечить поддержку стандартного клиентского метода loginAsync() , можно перегрузить маршрут проверки подлинности. Если клиент вызывает client.loginAsync('custom'); для входа, ваш маршрут должен быть следующим: /.auth/login/custom. Вы можете задать маршрут для контроллера пользовательской проверки подлинности с помощью MapHttpRoute().

config.Routes.MapHttpRoute("custom", ".auth/login/custom", new { controller = "CustomAuth" });

Совет

Подход с использованием loginAsync() гарантирует, что маркер проверки подлинности прикрепляется к каждому последующему вызову службы.

Получение сведений о пользователе, прошедшем проверку подлинности

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

// Get the SID of the current user.
var claimsPrincipal = this.User as ClaimsPrincipal;
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;

SID является производным от идентификатора пользователя, предоставленного поставщиком, и является статическим для данного пользователя и поставщика входа в систему. Идентификатор безопасности (SID) имеет значение NULL для недопустимых маркеров проверки подлинности.

Кроме того, служба приложений позволяет запрашивать конкретные утверждения от поставщика входа в систему. Каждый поставщик удостоверений может предоставлять больше сведений с помощью пакета SDK поставщика удостоверений. Например, можно использовать Graph API Facebook для получения сведений о друзьях. Вы можете задать утверждения, запрошенные в колонке поставщика на портале Azure. Некоторые утверждения требуют дополнительной настройки с использованием поставщика удостоверений.

Следующий код вызывает метод расширения GetAppServiceIdentityAsync для получения учетных данных входа, которые включают маркер доступа, необходимый для выполнения запросов к API Graph Facebook:

// Get the credentials for the logged-in user.
var credentials = await this.User.GetAppServiceIdentityAsync<FacebookCredentials>(this.Request);

if (credentials.Provider == "Facebook")
{
    // Create a query string with the Facebook access token.
    var fbRequestUrl = "https://graph.facebook.com/me/feed?access_token="
        + credentials.AccessToken;

    // Create an HttpClient request.
    var client = new System.Net.Http.HttpClient();

    // Request the current user info from Facebook.
    var resp = await client.GetAsync(fbRequestUrl);
    resp.EnsureSuccessStatusCode();

    // Do something here with the Facebook user information.
    var fbInfo = await resp.Content.ReadAsStringAsync();
}

Чтобы предоставить метод расширения GetAppServiceIdentityAsync, необходимо добавить выражение для System.Security.Principal.

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

В предыдущем разделе мы показали, как получить идентификатор пользователя, прошедшего проверку подлинности. По этому значению можно ограничить доступ к данным и другим ресурсам. Например, добавив в таблицы столбец userId и отфильтровав результаты запросов по идентификатору пользователя, вы получите простой способ ограничения возвращаемых данных только данными для авторизованных пользователей. Следующий код возвращает строки данных только в том случае, если SID совпадает со значением в столбце UserId таблицы TodoItem.

// Get the SID of the current user.
var claimsPrincipal = this.User as ClaimsPrincipal;
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;

// Only return data rows that belong to the current user.
return Query().Where(t => t.UserId == sid);

Метод Query() возвращает IQueryable, которым можно управлять с помощью LINQ для обработки фильтрации.

Отладка и устранение неполадок с пакетом SDK для сервера .NET

Служба приложений Azure предоставляет несколько методов отладки и устранения неполадок в приложениях ASP.NET.

Ведение журнала

Журналы диагностики службы приложений вы можете вести с помощью стандартной записи трассировки ASP.NET. Перед записью в журналы необходимо включить диагностику в серверной части мобильных приложений Azure.

Для включения диагностики и записи в журналы сделайте следующее:

  1. Выполните действия, описанные в разделе Включение ведения журналов приложений (Windows).

  2. Добавьте в файл с кодом следующую инструкцию using:

    using System.Web.Http.Tracing;
    
  3. Создайте модуль записи трассировки для записи из серверного приложения .NET в журналы диагностики следующим образом:

    ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
    traceWriter.Info("Hello, World");
    
  4. Повторно опубликуйте серверный проект и запустите серверную часть мобильных приложений Azure с ведением журнала.

  5. Скачайте и оцените журналы, как описано в разделе Доступ к файлам журнала.

Локальная отладка с проверкой подлинности

Вы можете запустить приложение локально, чтобы проверить изменения перед их публикацией в облаке. Для большинства серверных систем мобильных приложений Azure нажмите клавишу F5 во время работы в Visual Studio. Однако при проверке подлинности следует учитывать некоторые дополнительные рекомендации.

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

Убедитесь, что в мобильном внутреннем сервере установлен пакет Microsoft.Azure.Mobile.Server.Authentication . В приложении добавьте следующий код в класс запуска OWIN после применения MobileAppConfiguration к объекту HttpConfiguration:

app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions()
{
    SigningKey = ConfigurationManager.AppSettings["authSigningKey"],
    ValidAudiences = new[] { ConfigurationManager.AppSettings["authAudience"] },
    ValidIssuers = new[] { ConfigurationManager.AppSettings["authIssuer"] },
    TokenHandler = config.GetAppServiceTokenHandler()
});

В приведенном выше примере необходимо настроить параметры приложения authAudience и authIssuer в файле Web.config, задав для каждого из них значение URL-адреса корня приложения в формате HTTPS. Точно так же для параметра authSigningKey нужно задать значение ключа подписывания приложения.

Чтобы получить ключ подписывания, сделайте следующее:

  1. Перейдите в свое приложение на портала Azure
  2. Выберите Инструменты>Kudu>Перейти.
  3. На сайте управления Kudu щелкните Среда.
  4. Найдите значение для переменной WEBSITE_AUTH_SIGNING_KEY.

Используйте ключ подписывания для параметра authSigningKey в локальной конфигурации приложения. Теперь серверная часть мобильного приложения может проверять токены при локальном запуске, когда клиент получает токен из облачной конечной точки.