Utilisation du kit SDK ASP.NET Framework pour Azure Mobile Apps

Cette rubrique montre comment utiliser le kit SDK du serveur backend .NET dans les scénarios Azure App Service Mobile Apps. Le Kit de développement logiciel (SDK) Azure Mobile Apps vous permet de travailler avec des clients mobiles à partir de votre application ASP.NET.

Avertissement

Cet article décrit les informations relatives à la version de la bibliothèque v4.2.0, qui est superposée par la bibliothèque v5.0.0. Pour obtenir les informations les plus récentes, consultez l’article de la dernière version

Créer un back-end Azure Mobile Apps ASP.NET Framework

Vous pouvez créer une application ASP.NET Framework à l’aide de Visual Studio 2019.

  • Choisissez le modèle Application Web ASP.NET (.NET Framework). Si vous avez des difficultés à localiser ce modèle, sélectionnez C#, Toutes les plateformes et Web.
  • Après avoir sélectionné un nom et un emplacement pour l’application, sélectionnez le modèle de projet API Web. La collection correcte des services de base pour votre application sera installée.

Télécharger et initialiser le SDK

Le kit SDK est disponible sur NuGet.org et fournit les fonctionnalités de base nécessaires pour commencer à utiliser Azure Mobile Apps. Pour installer le package :

  1. Cliquez avec le bouton droit sur le projet, puis sélectionnez Gérer les packages NuGet....
  2. Sous l’onglet Parcourir, entrez Microsoft.Azure.Mobile.Server dans la zone de recherche et appuyez sur Entrée.
  3. Sélectionnez le package Microsoft.Azure.Mobile.Server.Quickstart.
  4. Cliquez sur Installer.
  5. Suivez les instructions fournies pour terminer l’installation.

Répétez le processus pour installer également Microsoft.Owin.Host.SystemWeb.

Remarque

Ne mettez pas à jour les packages qui sont utilisés comme dépendances, tels que Newtonsoft.JSON ou System.IdentityModel.Jwt. Dans de nombreux cas, les API de ces packages ont changé et sont désormais incompatibles avec Azure Mobile Apps pour ASP.NET Framework.

Initialiser le projet de serveur

Un projet de serveur Azure Mobile Apps est initialisé de la même façon que les autres projets ASP.NET Framework, en incluant une classe de démarrage OWIN. Pour ajouter une classe de démarrage OWIN :

  1. Cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>Nouvel élément.

  2. Sélectionnez Web>Général, puis sélectionnez le modèle Classe de démarrage OWIN.

  3. Entrez le nom Startup.cs comme nom de démarrage.

  4. Le contenu du fichier Startup.cs doit être similaire au code suivant :

    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, l’espace de noms et le nom de la classe seront différents, en fonction de votre projet. Plus précisément, vous devez remplacer le contenu de la méthode Configuration() et ajuster les directives using en conséquence.

Pour activer des fonctionnalités spécifiques, vous devez appeler les méthodes d’extension sur l’objet MobileAppConfiguration avant d’appeler ApplyTo. Par exemple, le code suivant ajoute les itinéraires par défaut à tous les contrôleurs d’API avec l’attribut [MobileAppController] lors de l’initialisation :

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

La configuration suivante est considérée comme une utilisation « normale » qui permet à la fois aux contrôleurs de table et d’API utilisant Entity Framework d’accéder à un service SQL.

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

Les méthodes d’extension utilisées sont les suivantes :

  • AddMobileAppHomeController() fournit la page d’accueil Azure Mobile Apps par défaut.
  • MapApiControllers() fournit des fonctionnalités d’API personnalisées pour les contrôleurs WebAPI assortis de l’attribut [MobileAppController].
  • AddTables() fournit un mappage des points de terminaison /tables aux contrôleurs de table.
  • AddTablesWithEntityFramework() est un raccourci pour le mappage des points de terminaison /tables utilisant des contrôleurs basés contrôleurs basés sur Entity Framework.
  • MapLegacyCrossDomainController() fournit des en-têtes CORS standard pour le développement local.

Extensions de Kit de développement logiciel (SDK)

Les packages d’extension NuGet suivants fournissent différentes fonctionnalités mobiles que votre application peut utiliser. Les extensions s’activent à l’aide de l’objet MobileAppConfiguration lors de l’initialisation.

  • Microsoft.Azure.Mobile.Server.Quickstart prend en charge la configuration de base de Mobile Apps. S’ajoute à la configuration en appelant la méthode d’extension UseDefaultConfiguration pendant l’initialisation. Cette extension comprend les extensions suivantes : packages Notifications, Authentication, Entity, Tables, Cross-domain et Home.
  • Microsoft.Azure.Mobile.Server.Home implémente la page par défaut cette application mobile est opérationnelle pour la racine du site web. S’ajoute à la configuration en appelant la méthode d’extension AddMobileAppHomeController .
  • Microsoft.Azure.Mobile.Server.Tables inclut des classes pour l’utilisation des données et configure le pipeline de données. S’ajoute à la configuration en appelant la méthode d’extension AddTables .
  • Microsoft.Azure.Mobile.Server.Entity permet à Entity Framework d’accéder aux données de la base de données SQL. S’ajoute à la configuration en appelant la méthode d’extension AddTablesWithEntityFramework .
  • Microsoft.Azure.Mobile.Server.Authentication Active l’authentification et configure l’intergiciel OWIN utilisé pour valider les jetons. S’ajoute à la configuration en appelant les méthodes d’extension AddAppServiceAuthentication et IAppBuilder.UseAppServiceAuthentication.
  • Microsoft.Azure.Mobile.Server.Notifications active les notifications Push et définit un point de terminaison d’inscription Push. S’ajoute à la configuration en appelant la méthode d’extension AddPushNotifications .
  • Microsoft.Azure.Mobile.Server.CrossDomain crée un contrôleur qui fournit des données aux navigateurs web hérités à partir de votre application mobile. S’ajoute à la configuration en appelant la méthode d’extension MapLegacyCrossDomainController .
  • Microsoft.Azure.Mobile.Server.Login fournit la méthode AppServiceLoginHandler.CreateToken(), qui est une méthode statique utilisée dans le cadre des scénarios d’authentification personnalisés.

Publier le projet de serveur

Cette section vous explique comment publier votre projet de backend .NET à partir de Visual Studio. Vous pouvez publier votre application à l’aide d’autres méthodes. Pour plus d’informations, consultez la documentation relative à Azure App Service.

  1. Avec Visual Studio, développez le projet pour restaurer des packages NuGet.
  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis cliquez sur Publier.
  3. Si vous n’avez pas publié ce projet auparavant, vous allez configurer la publication.
    • Sélectionnez Azure pour la cible.
    • Sélectionnez Azure App Service (Windows) pour la cible spécifique.
    • Sélectionnez l’instance de service d’application sur laquelle vous souhaitez effectuer le déploiement. Si vous n’en avez pas, utilisez + pour en créer un.
    • Cliquez sur Terminer.
  4. Si vous n’avez pas lié de base de données SQL auparavant, cliquez sur Configurer en regard de la base de données SQL.
    • Sélectionnez Azure SQL Database.
    • Sélectionnez votre base de données. Si vous n’en avez pas ou si vous souhaitez en utiliser une autre, cliquez sur + pour créer une nouvelle base de données et un serveur.
    • Entrez MS_TableConnectionString comme nom de la chaîne de connexion de base de données. Renseignez le nom d’utilisateur et le mot de passe dans les zones prévues à cet effet.
    • Cliquez sur Terminer
  5. Cliquez sur Publier.

La publication sur Azure prend un certain temps. Pour plus d’informations, consultez la documentation relative à Visual Studio.

Définir un contrôleur de table

Définissez un contrôleur de table pour exposer une table SQL aux clients mobiles. La configuration d’un contrôleur de table requiert trois étapes :

  1. Créer une classe d’objet de transfert de données (DTO).
  2. Configurer une référence de table dans la classe DbContext Mobile.
  3. Créer un contrôleur de table.

Un objet de transfert de données (DTO) est un objet C# simple qui hérite de EntityData. Par exemple :

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

Le DTO est utilisé pour définir la table au sein de la base de données SQL. Pour créer l’entrée de base de données, ajoutez une propriété DbSet<> à la classe DbContext que vous utilisez :

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()));
    }
}

Enfin, créez un nouveau contrôleur :

  1. Cliquez avec le bouton droit sur le dossier Controllers.

  2. Sélectionnez API web>Contrôleur API web 2 – Vide

  3. Entrez un nom pour le contrôleur.

  4. Remplacez le contenu du nouveau contrôleur par le code suivant :

    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);
        }
    }
    

Ajuster la taille de pagination des tables

Par défaut, Azure Mobile Apps retourne 50 enregistrements par demande. La pagination permet de s’assurer que le client n’occupe pas son thread d’interface utilisateur ni le serveur pendant trop longtemps et optimise son expérience utilisateur. Pour modifier la taille de pagination des tables, augmentez la « taille de requête autorisée » côté serveur et la taille de page côté client. La « taille de requête autorisée » côté serveur peut être ajustée à l’aide de l’attribut EnableQuery :

[EnableQuery(PageSize = 500)]

Vérifiez que la valeur de PageSize est supérieure ou égale à la taille demandée par le client. Reportez-vous aux procédures de la documentation destinée au client pour savoir comment modifier la taille de pagination pour le client.

Définir un contrôleur d’API personnalisé

Le contrôleur d’API personnalisé fournit les fonctionnalités de base au serveur principal de votre application mobile en exposant un point de terminaison. Vous pouvez enregistrer un contrôleur d’API mobile spécifique à l’aide de l’attribut [MobileAppController]. L’attribut MobileAppController enregistre la route, définit le sérialiseur JSON Mobile Apps et active la vérification de version du client.

Le contenu du contrôleur d’API personnalisé est le suivant :

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

Une fois configuré avec l’attribut MobileAppController, vous pouvez définir l’API personnalisée de la même façon que n’importe quelle autre API Web.

Utiliser l’authentification

Azure Mobile Apps fait appel à l’authentification/autorisation App Service pour sécuriser votre backend mobile. Cette section vous explique comment effectuer les tâches suivantes liées à l’authentification dans votre projet de serveur principal .NET :

Ajouter l’authentification à un projet de serveur

Vous pouvez ajouter l’authentification à votre projet de serveur en étendant l’objet MobileAppConfiguration et en configurant l’intergiciel OWIN.

  1. Dans Visual Studio, installez le package Microsoft.Azure.Mobile.Server.Authentication .

  2. Dans le fichier de projet Startup.cs, ajoutez la ligne de code suivante au début de la méthode Configuration :

    app.UseAppServiceAuthentication(config);
    

    Ce composant intergiciel (middleware) OWIN valide les jetons émis par la passerelle App Service associée.

  3. Ajoutez l’attribut [Authorize] à tous les contrôleurs ou méthodes nécessitant une authentification.

Utiliser l’authentification personnalisée pour votre application

Important

Pour activer l’authentification personnalisée, vous devez d’abord activer l’authentification d’App Service sans sélectionner un fournisseur pour votre App Service dans le portail Azure. Cela active la variable d’environnement WEBSITE_AUTH_SIGNING_KEY lorsqu’elle est hébergée.

Si vous ne souhaitez pas utiliser l’un des fournisseurs d’authentification/d’autorisation App Service, vous pouvez implémenter votre propre système de connexion. Pour faciliter la génération de jetons d’authentification, installez le package Microsoft.Azure.Mobile.Server.Login . Fournissez votre propre code pour valider les informations d’identification utilisateur. Par exemple, vous pouvez définir des mots de passe salés et hachés dans une base de données. Dans l’exemple ci-dessous, la méthode isValidAssertion() (définie ailleurs) est chargée de ces vérifications.

L’authentification personnalisée est exposée en créant une classe ApiController et en exposant les actions register et login. Le client doit utiliser une interface utilisateur personnalisée pour collecter les informations auprès de l’utilisateur. Les informations sont ensuite envoyées à l’API avec un appel HTTP POST standard. Une fois que le serveur a validé l’assertion, un jeton est émis à l’aide de la méthode AppServiceLoginHandler.CreateToken() . La classe ApiController ne doit pas utiliser l’attribut [MobileAppController].

Un exemple d’action 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();
    }
}

Dans l’exemple précédent, LoginResult et LoginResultUser sont des objets sérialisables qui exposent les propriétés requises. Le client attend que les réponses de connexion soient renvoyées en tant qu’objets JSON de la forme suivante :

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

La méthode AppServiceLoginHandler.CreateToken() inclut un paramètre audience et un paramètre émetteur. Ces deux paramètres sont définis sur l’URL de la racine de votre application à l’aide du schéma HTTPS. De la même manière, vous devez définir secretKey en tant que clé de signature de votre application. Ne distribuez pas la clé de signature dans un client, car elle peut être utilisée pour générer des clés et usurper l’identité d’utilisateurs. Hébergé dans App Service, vous pouvez obtenir la clé de signature en faisant référence à la variable d’environnement WEBSITE_AUTH_SIGNING_KEY. Si vous en avez besoin dans un contexte de débogage local, suivez les instructions de la section Débogage local avec authentification afin de récupérer la clé et de la stocker en tant que paramètre d’application.

Le jeton émis peut également inclure d’autres revendications et une date d’expiration. Le jeton émis doit inclure au minimum une revendication d’objet (sub).

Vous pouvez prendre en charge la méthode cliente loginAsync() standard en surchargeant l’itinéraire d’authentification. Si le client appelle client.loginAsync('custom'); pour se connecter, l’itinéraire doit être /.auth/login/custom. Vous pouvez définir l’itinéraire du contrôleur d’authentification personnalisée à l’aide de MapHttpRoute():

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

Conseil

L’utilisation de l’approche loginAsync() permet de s’assurer que le jeton d’authentification est joint à chaque appel supplémentaire au service.

Récupérer des informations utilisateur authentifiées

Lorsqu’un utilisateur est authentifié par App Service, vous pouvez accéder à l’ID utilisateur affecté et à d’autres informations dans votre code de serveur principal .NET. Les informations utilisateur peuvent être utilisées pour prendre des décisions d’autorisation sur le backend. Le code suivant récupère l’ID utilisateur associé à une demande :

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

Le SID est dérivé de l’ID utilisateur spécifique au fournisseur et est statique pour un utilisateur donné et un fournisseur de connexion. Le SID a la valeur null pour les jetons d’authentification non valides.

App Service vous permet également de demander des revendications spécifiques à votre fournisseur de connexion. Chaque fournisseur d’identité peut fournir des informations supplémentaires à l’aide du Kit de développement logiciel (SDK) du fournisseur d’identité. Par exemple, vous pouvez utiliser l’API Graph Facebook pour les informations relatives aux amis. Vous pouvez spécifier des revendications qui sont demandées dans le panneau du fournisseur au sein du portail Azure. Certaines revendications nécessitent plus de configuration auprès du fournisseur d’identité.

Le code suivant appelle la méthode d’extension GetAppServiceIdentityAsync pour obtenir les informations d'identification de connexion, qui incluent l'accès au jeton nécessaire pour effectuer des requêtes par rapport à l’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();
}

Ajoutez une instruction using pour System.Security.Principal afin de fournir la méthode d’extension GetAppServiceIdentityAsync .

Limiter l’accès aux données pour les utilisateurs autorisés

Dans la section précédente, nous vous avons montré comment récupérer l’identificateur d’utilisateur d’un utilisateur authentifié. Vous pouvez restreindre l’accès aux données et à d’autres ressources en fonction de cette valeur. Par exemple, l’ajout d’une colonne userId à des tables et le filtrage des résultats de la requête par l’ID utilisateur constituent un moyen simple de limiter les données renvoyées aux utilisateurs autorisés. Le code suivant retourne des lignes de données uniquement lorsque le SID correspond à la valeur dans la colonne UserId de la table 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);

La méthode Query() renvoie un paramètre IQueryable qui peut être manipulé par LINQ pour gérer le filtrage.

Déboguer et résoudre les problèmes du SDK serveur .NET

Azure App Service fournit plusieurs techniques de débogage et de résolution des problèmes pour les applications ASP.NET.

Journalisation

Vous pouvez écrire dans les journaux de diagnostics App Service à l’aide du traçage ASP.NET standard. Avant de pouvoir écrire dans les journaux, vous devez activer les diagnostics sur votre backend Azure Mobile Apps.

Pour activer les diagnostics et écrire dans les journaux d’activité :

  1. Suivez les étapes d’Activer la journalisation des applications (Windows).

  2. Ajoutez l’instruction using suivante dans votre fichier de code :

    using System.Web.Http.Tracing;
    
  3. Créez un writer de suivi pour écrire à partir du serveur principal .NET dans les journaux de diagnostic, comme ceci :

    ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
    traceWriter.Info("Hello, World");
    
  4. Publiez à nouveau votre projet de serveur et accédez au backend Azure Mobile Apps pour exécuter le chemin d’accès du code avec la journalisation.

  5. Téléchargez et évaluez les journaux d’activité, comme décrit dans Accéder aux fichiers journaux.

Débogage local avec authentification

Vous pouvez exécuter localement votre application afin de tester les modifications avant de les publier dans le cloud. Pour la plupart des backends Azure Mobile Apps, appuyez sur F5 lorsque vous êtes dans Visual Studio. Toutefois, certains points supplémentaires doivent être pris en compte en utilisant l’authentification.

Vous devez disposer d’une application mobile basée sur le cloud avec l’authentification/l’autorisation App Service configurées, et votre client doit posséder le point de terminaison du cloud spécifié en tant qu’hôte secondaire de connexion. Consultez la documentation associée à votre plateforme cliente pour connaître la procédure appropriée.

Assurez-vous que Microsoft.Azure.Mobile.Server.Authentication est installé sur votre backend mobile. Ensuite, dans la classe de démarrage OWIN de votre application, ajoutez les éléments suivants, après que MobileAppConfiguration a été appliquée à votre HttpConfiguration :

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

Dans l’exemple précédent, vous devez configurer les paramètres d’application authAudience et authIssuer de votre fichier web.config sur l’URL de la racine de votre application à l’aide du schéma HTTPS. De la même manière, vous devez définir authSigningKey en tant que valeur de clé de signature de votre application.

Pour obtenir la clé de signature :

  1. Accédez à votre application dans le portail Azure
  2. Cliquez sur Outils>Kudu>Go.
  3. Dans le site de gestion Kudu, cliquez sur Environment(Environnement).
  4. Recherchez la valeur de WEBSITE_AUTH_SIGNING_KEY.

Utilisez la clé de signature pour le paramètre authSigningKey dans la configuration de votre application locale. Lorsqu’il s’exécute localement, votre backend mobile est maintenant équipé pour valider les jetons que le client obtient à partir du point de terminaison basé sur le cloud.