OData
OData, Entity Framework et Access Control (ACS) de Windows Azure
Télécharger l'exemple de code
Dans cet article, je vais vous montrer comment implémenter Open Data Protocol (OData) avec Entity Framework étant exposé avec les services Windows Communication Foundation (WCF) RESTful et sécurisé avec le service Access Control (ACS) de Windows Azure.
Comme la plupart des développeurs, il m'arrive souvent d'essayer d'utiliser une combinaison de technologies de manières nouvelles et variées pour réaliser mon projet aussi efficacement que possible tout en apportant une solution souple et facile à gérer. Cet objectif peut être difficile à atteindre, notamment lorsque le projet nécessite des données à exposer rapidement et en toute sécurité.
J'ai été invité récemment à créer un service Web sécurisé pour une application de base de données et Web existante. Je ne voulais vraiment pas implémenter l'ensemble du code CRUD (Create, Read, Update, Delete – Créer, Lire, Mettre à jour, Supprimer). J'étais très tenté de ne créer que des contrats de service personnalisés, des contrats d'opération et des contrats de données afin de régir avec précision le mode d'exposition et de consommation des données via les services. Mais je savais qu'il y avait une voie plus avantageuse à suivre. J'ai commencé à rechercher les diverses manières dont je disposais pour réaliser mon objectif et ai jugé qu'il existait un potentiel avec OData (ou « Oh ! Data », comme je me plais à l'appeler). Le problème était qu'OData en lui-même n'était pas sécurisé de manière acceptable, selon moi. J'ai eu besoin d'ajouter une couche de sécurité supplémentaire au-dessus du service OData afin de m'assurer qu'il serait sécurisé correctement. Comme je commençais à assembler le tout, j'ai découvert ACS, qui est idéal pour implémenter une authentification fédérée et un service d'autorisation basés sur le cloud. C'était exactement ce dont j'avais besoin. Puis la révélation est arrivée. Je me suis rendu compte que j'obtenais la solution que je voulais en connectant ACS à OData.
Or, j'ai pensé à implémenter des contrats de service personnalisés, et il y a une place pour cette approche, notamment lorsqu'une couche d'abstraction est nécessaire devant un modèle de données et qu'elle doit protéger les entités de base de données contre une exposition directe aux utilisateurs d'un service. Toutefois, étant donné le temps que prend la création d'un document approprié sur le mode de consommation du service et son ajout aux tâches supplémentaires nécessaires à la configuration de la sécurité, (« MessageCredential » et « TransportWithMessageCredentials »), le projet peut rapidement devenir incontrôlable. Je m'inquiétais aussi du fait que des méthodes supplémentaires seraient nécessaires ou demandées, pour une raison ou une autre, afin de prendre en charge le mode d'utilisation des services, lesquels, à leur tour, nécessiteraient davantage de temps, de maintenance et de personnalisation. Même si l'implémentation du service utilisait directement Entity Framework au lieu d'ADO.NET, il pouvait encore être nécessaire de créer l'ensemble du code pour conserver la synchronisation de la couche de données. Étant donné la présence de quelques dizaines de tables, cette tâche pouvait être extrêmement pénible. De plus, la création et la mise à jour d'autres informations de documentation et d'implémentation nécessaires aux utilisateurs finaux pour utiliser mon service rendaient cette proposition beaucoup plus compliquée à gérer.
Un moyen plus simple
Après avoir identifié les technologies principales, j'ai cherché d'autres technologies pour combler les lacunes et créer une solution cohésive. L'objectif consistait à limiter la quantité de code nécessaire devant être écrite ou mise à jour, tout en activant en toute sécurité mes services OData WCF RESTful. Les technologies que j'ai associées sont les suivantes : ACS, OData, les modèles de données d'entité, les services de données WCF avec les autorisations d'entité et une implémentation de sécurité Windows Azure personnalisée. Chacune de ces technologies fournit déjà une valeur significative par elle-même, mais lorsque ces technologies sont combinées, leur valeur augmente de manière exponentielle. La Figure 1 montre une vue d'ensemble de la façon dont ces technologies fonctionneront lorsqu'elles seront implémentées.
Figure 1 Vue d'ensemble d'ACS avec une interception de sécurité
Avant de tenter de combiner toutes ces technologies, j'ai dû prendre du recul, bien comprendre chacune d'entre elles et la manière dont elles pouvaient influencer ce projet. Grâce à cette compréhension, j'ai pu déterminer comment les combiner et quels étaient les éléments nécessaires aux utilisateurs d'autres technologies pour consommer mes services.
Qu'est-ce qu'ACS ?
ACS est fourni sous la forme d'un composant de la plateforme Windows Azure. ACS me permet de configurer mon propre fournisseur basé sur le cloud pour les authentifications et autorisations fédérées. Je l'utilise pour sécuriser mes services OData WCF, mais il peut aussi servir à sécuriser une application. ACS est un service basé sur le cloud qui aide à combler la lacune de sécurité lorsqu'il est nécessaire d'implémenter une connexion unique (SSO) dans plusieurs applications, services ou produits prenant en charge diverses implémentations SSO multi-plateformes ou multi-domaines. Un compte Windows Azure permet d'accéder à beaucoup plus d'informations. Vous pouvez vous inscrire à une évaluation gratuite sur le site windowsazure.com. Pour en savoir plus sur ACS, consultez bit.ly/zLpIbw.
Qu'est-ce qu'OData et à quoi sert-il ?
OData est un protocole Web qui sert à interroger les données, à les mettre à jour, ainsi qu'à les exposer à l'aide d'une syntaxe normalisée. OData tire parti de technologies telles que HTTP, XML, JSON et Atom Publishing Protocol pour fournir un accès différent aux données. L'implémentation d'OData avec Entity Framework et les services de données WCF offre un grand nombre d'avantages intéressants.
J'ai commencé à me demander pourquoi je ne l'utiliserais pas à la place des contrats WCF personnalisés. La réponse a été très simple. La raison la plus pratique était l'utilisation de la documentation du service déjà disponible et d'une syntaxe normalisée prenant en charge le mode d'accès aux données depuis le service. Comme j'ai écrit des dizaines de services, j'ai l'impression d'avoir toujours besoin d'ajouter une autre méthode après avoir fourni des services personnalisés. De plus, les utilisateurs de services personnalisés ont tendance à demander de plus en plus de fonctionnalités.
Pour plus d’informations sur OData et les conventions de l'URI pour OData, consultez les sites suivants :
- Site principal OData : odata.org
- Conventions de l'URI pour OData : bit.ly/NRalFb
- Exemple de service OData de Netflix : bit.ly/9UZjRd
OData avec Entity Framework et les services de données WCF
L'utilisation d'OData avec les services de données WCF et Entity Framework expose les fonctionnalités standard pour prendre en charge la récupération et l'enregistrement des données grâce à une méthode déjà documentée avec peu de code d'implémentation. Lorsque j'ai commencé à créer mon modèle de données d'entité pour le format EDMX (Data Services Packaging Format) et que je l'ai lié à mon service WCF via les services de données, j'étais très sceptique. Mais cela a fonctionné parfaitement. Toutes les entités que j'avais incluses dans mon EDMX ont été automatiquement incluses et exposées dans mon service dans une implémentation RESTful. La figure 2 montre un exemple de code.
Figure 2. Implémentation des services de données OData WCF
using System.Data.Services; using System.Data.Services.Common; namespace WCFDataServiceExample { public class NorthwindService : DataService<NorthwindEntities> { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { // Give full access to all of the entities. config.SetEntitySetAccessRule("*", EntitySetRights.All); // Page size will change the max number of rows returned. config.SetEntitySetPageSize("*", 25); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } } }
J'ai créé un EDMX et l'ai lié à quelques tables de ma base de données (Northwind Sample Database). J'ai ensuite lié mes entités de base de données à mon service de données WCF et exposé toutes les entités en utilisant la méthode « SetEntitySetAccessRule » avec un attribut caractère générique * pour désigner toutes les entités. Cela m'a permis de définir diverses autorisations sur mes entités pour l'accès en lecture, écriture et interrogation, ainsi que pour la définition de la taille de page, comme le montre la figure 2. Le code montré est l'implémentation intégrale du code des services de données OData WCF.
Les contrats de service, d'opération et de données sont contrôlés principalement via la configuration dans l'initialisation du service fourni. Dans la méthode d'initialisation, je peux définir diverses autorisations correspondant à la façon dont j'aimerais exposer mes entités et le niveau d'accès que j'aimerais fournir à ceux qui cherchent à utiliser mes services. Je pourrais même utiliser des modèles T4 pour créer une couche abstraite ou une couche de modèle au-dessus des entités avec des noms d'entité personnalisés. Cela rendrait les choses plus claires pour l'utilisateur de mes services. Je pourrais même définir les autorisations pour une table spécifique, ou je pourrais définir le nom de table avec les paramètres de sécurité appropriés pour une protection même moindre. Voici un exemple d'attribution d'un accès en lecture à la table Customer (Client) :
Beaucoup d'implémentations de sécurité diverses peuvent être activées avec OData et les services de données WCF, mais, pour le moment, je me préoccupe seulement de savoir comment protéger mes services WCF avec ACS associé avec les règles d'accès du service de données.
La figure 3 présente une liste rapide des technologies utilisées et des raisons pour lesquelles ces technologies peuvent être utilisées.
Figure 3. Technologies utilisées et raisons de leur emploi
Technologie | Raison de l'utiliser |
ACS | Permet de sécuriser les services à l'aide d'un module de sécurité fédéré basé sur le cloud pour l'authentification et l'autorisation |
OData | Fournit une syntaxe standard pour interroger et mettre à jour les données tout en exploitant des technologies courantes telles que HTTP, JSON, Atom Publishing Protocol et XML. |
Modèles de données d'entité | Permettent de créer rapidement un accès aux données courantes pour un niveau de base de données tout en fournissant également des contrats de données de tables sérialisables dans une base de données |
Services de données WCF avec autorisations d'entité | Exposent le contrat de données Entity Framework avec le niveau d'autorisations approprié pour CRUD sous la forme d'un service WCF RESTful |
Implémentation de sécurité Windows Azure personnalisée | Protège les services (ici les services OData) pour les empêcher d'être utilisés sans que le niveau de sécurité approprié, par exemple un jeton ou un certificat, ne leur soit appliqué. |
Chacune de ces technologies s'accompagne toujours de compromis basés sur le projet, mais j'ai découvert que les combiner permettait d'économiser du temps dans la configuration initiale et de réduire les tâches de maintenance, tout en demandant moins de temps et en apportant des gains colossaux, notamment lorsque j'avais besoin d'exposer mes données en toute sécurité et de fournir des méthodes d'accès aux données courantes avec une syntaxe normalisée.
En résumé
Avec une assez bonne compréhension de l'utilisation combinée d'OData, d'Entity Framework et des services de données WCF, j'ai pu appliquer d'autres fonctionnalités de sécurité à cette technologie en exploitant ACS. Quelques options se présentaient pour protéger mon service contre les accès, notamment la définition de diverses autorisations sur les entités ou l'ajout d'intercepteurs de requête pour empêcher l'utilisation des services ou contrôler comment mon service pouvait être utilisé.
Toutefois, l'implémentation d'intercepteurs de requête ou la définition d'autorisations aurait été pénible et l'ajout d'une couche de sécurité au-dessus de mon service pour l'empêcher d'être utilisé a été préféré à l'écriture de code supplémentaire. Il serait idéal d'implémenter un mécanisme de sécurité courant permettant aux parties de confiance ou aux sociétés externes d'accéder à mes services. Ensuite, je pourrais utiliser une combinaison de cette sécurité de même qu'une protection d'entité pour offrir à mes services l'implémentation la mieux sécurisée et présentant la meilleure flexibilité.
L'utilisation de cette approche nécessiterait que les consommateurs de mon service commencent par s'authentifier via ACS et obtiennent un jeton d'accès valide. Sans ce jeton d'accès, les services seraient limités. Des jetons d'accès valides seraient nécessaires dans l'en-tête de demande pour permettre l'accès à mon service. Après que l'utilisateur de mon service ait reçu son autorisation, j'appliquerais une sécurité précise sur les entités pour n'établir qu'un accès autorisé aux données ou à mes entités.
Installation et configuration d'ACS
Des tâches d'installation et de configuration sont requises pour implémenter ACS. La figure 4 montre une liste des éléments que j'installe pour cet exemple.
Figure 4. Installation d'ACS
Configuration | Valeurs |
Espace de noms ACS | WCFoDataACS |
Application de la partie qui répond | Nom : wcfodataacsexampleDevelopment Mode : Conserver les valeurs par défaut (entrer les paramètres manuellement) Domaine : http://localhost/WCFDataServiceExample/<nom du service>.svc URL de retour : Conserver la valeur par défaut (vide) URL d'erreur : Conserver la valeur par défaut (vide) Format du jeton : SWT Stratégie de chiffrement du jeton : Conserver la valeur par défaut (none) Durée de vie du jeton : Conserver la valeur par défaut (600) |
Paramètres d'authentification | Fournisseurs d'identité : Désactiver le Windows Live ID Groupe de règles : Cliquer sur Créer un groupe de règles. Remarque : j'ai créé différents paramètres pour le développement, les tests et la production. |
Paramètres de signature des jetons | Cliquer sur le bouton Générer Date d’entrée en vigueur : Conserver les valeurs par défaut Date d’expiration : Conserver les valeurs par défaut |
Groupe de règles | Remarque : Selon mes paramètres, le groupe de règles sera créé automatiquement, mais je dois encore ajouter la configuration des déclarations. |
Configuration des réclamations | Section If : Système de contrôle d'accès : Sélectionné Type de la déclaration d'entrée : Conserver la valeur par défaut (any) Valeur de la réclamation d'entrée : Conserver la valeur par défaut (any) Section Then : Type de la déclaration de sortie : Conserver la valeur par défaut (type de déclaration d'entrée relais) Valeur de la déclaration de sortie : Conserver la valeur par défaut (valeur de la déclaration d'entrée relais) Informations sur les règles : Description : Conserver la valeur par défaut ou entrer une description |
Identité de service dans Windows | Nom : le nom d'utilisateur à fournir aux autres (dans cet exemple, j'ai utilisé wcfodataacsDevUser) Description : Conserver les valeurs par défaut (ou entrer une description pour l'utilisateur) Domaine : http://localhost/WCFDataServiceExample/<nom du service>.svc Paramètres des informations d'identification : Type : Sélectionner le mot de passe Mot de passe : Entrer le mot de passe voulu Date d’entrée en vigueur : Conserver les valeurs par défaut Date d’expiration : Conserver les valeurs par défaut Remarque : Plusieurs options sont disponibles pour le mode d'authentification d'un utilisateur dans les services créés, mais, pour plus de commodité, j'ai utilisé une entrée de mot de passe comme type d'information d'identification. D'autres options sont disponibles, par exemple l'utilisation d'un certificat x509 ou d'une clé symétrique, qui peut assurer un niveau de sécurité supérieur, mais j'ai essayé d'utiliser une option de base pour cet exemple. |
Après avoir installé ACS, j'ai pu sécuriser mes services OData WCF RESTful. Avant de pouvoir les sécuriser, j'ai d'abord dû implémenter un module de sécurité personnalisé pour intercepter les demandes et valider la sécurité pour empêcher les accès non autorisés.
Implémentation de la sécurité ACS
À titre d'exemple, j'ai implémenté la sécurité à l'aide d'un module HTTP personnalisé. Ce module intercepte les demandes effectuées à mon service et les valide si l'authentification et l'autorisation appropriées ont été obtenues. Sans ce module HTTP, mes services seraient sécurisés uniquement au niveau entité, en fonction des paramètres de la configuration du service de données.
Dans ce cas, j'ai sécurisé ces services avec ACS ; ainsi, les demandes ont été interceptées, puis le niveau de sécurité approprié a été recherché pour vérifier que l'utilisateur du service avait obtenu le niveau d'autorisation approprié. Comme indiqué précédemment, la sécurité affinée a pu être implémentée au niveau entité lorsque l'utilisateur du service a obtenu l'autorisation d'accès.
Lors de l'implémentation de l'interface IHTTPModule, j'ai choisi d'ajouter des fonctionnalités supplémentaires. J'ai donc exposé des parties des métadonnées du service afin de permettre aux utilisateurs du service de générer automatiquement des classes (comme pour l'ajout d'un autre service Web). J'ai ajouté ces sections de code sous la forme d'attributs configurables pouvant être activés ou désactivés pour plus de sécurité, pour les tests et pour faciliter la tâche d'intégration.
La figure 5 montre du code qui intercepte les demandes et effectue la validation de sécurité appropriée.
Figure 5. Validation de sécurité
using System; using System.Collections.Generic; using System.Configuration; using System.Web; using Microsoft.AccessControl2.SDK; namespace Azure.oAuth.SecurityModule { internal class SWTModule : IHttpModule { // Service namespace setup in Windows Azure string _serviceNamespace = ConfigurationManager.AppSettings["serviceNamespace"]; // ACS name string _acsHostName = ConfigurationManager.AppSettings["acsHostname"]; // The key for which the service was signed string _trustedSigningKey = ConfigurationManager.AppSettings["trustedSigningKey"]; // The URL that was setup in the rely party in Windows Azure string _trustedAudience = ConfigurationManager.AppSettings["trustedAudience"]; // Setting to allow the metadata to be shown bool _enableMetaData = Convert.ToBoolean(ConfigurationManager.AppSettings["enableMetadata"]); // Setting to disable or enable the security module bool _disableSecurity = Convert.ToBoolean(ConfigurationManager.AppSettings["disableSecurity"]); const string _metaData = "$metadata"; private void context_BeginRequest(object sender, EventArgs e) { if (!_disableSecurity) { string tempAcceptableURLs = String.Empty; // Check if the audiencename has trailing slash tempAcceptableURLs = _trustedAudience.ToLower(); if (tempAcceptableURLs.Substring(_trustedAudience.Length - 1, 1) == "/") { tempAcceptableURLs = tempAcceptableURLs.Substring(0, _trustedAudience.Length - 1); } // First check if the person is requesting the WSDL or .svc if (_enableMetaData != false && HttpContext.Current.Request.Url.AbsoluteUri.ToLower() != tempAcceptableURLs && HttpContext.Current.Request.Url.AbsoluteUri.ToLower() != tempAcceptableURLs + _metaData && HttpContext.Current.Request.Url.AbsoluteUri.ToLower() != tempAcceptableURLs + "/" && HttpContext.Current.Request.Url.AbsoluteUri.ToLower() != tempAcceptableURLs + "/" + _metaData) { // SWT Validation... // Get the authorization header string headerValue = ttpContext.Current.Request.Headers.Get("Authorization"); // Check that a value is there if (string.IsNullOrEmpty(headerValue)) { throw new ApplicationException("unauthorized-1.1"); } // Check that it starts with 'WRAP' if (!headerValue.StartsWith("WRAP ")) { throw new ApplicationException("unauthorized-1.2"); } // ... <code truncated> ... } } } } }
Windows Azure SDK
J'ai extrait une classe de Windows Azure SDK pour effectuer des validations de jetons pour cette implémentation. Le projet se trouve à l'adresse bit.ly/utQd3S. Après avoir installé le kit de développement logiciel, j'ai copié le fichier nommé « tokenvalidator.cs » dans un nouveau projet. Dans cette classe spécifique, j'ai appelé la méthode de validation pour déterminer si l'utilisateur était autorisé via les informations configurées dans ACS. Pour simplifier cette implémentation, j'ai créé une DLL personnalisée avec le seul mécanisme de sécurité nécessaire. Après avoir créé l'assembly, il suffisait d'avoir une référence à la DLL de sécurité avec mon service OData WCF. Résultat : une implémentation protégée et sécurisée.
Implémentation du service OData sécurisé
Avec l'amélioration de sécurité supplémentaire en place, la sécurisation du service OData WCF devenait simple. Il suffisait d'avoir une référence à l'assembly « Azure.AccessControl.SecurityModule » et de l'ajouter aux paramètres de configuration supplémentaires. Les fonctionnalités de sécurité seraient ensuite activées. La figure 6 illustre les paramètres de configuration de sécurité.
Figure 6. Paramètres de configuration de sécurité
<appSettings> <add key="acsHostName" value="accesscontrol.windows.net" /> <add key="serviceNamespace" value="Service Namespace" /> <add key="trustedAudience" value="http://localhost/WCFDataServiceExample/NorthwindService.svc/" /> <add key="trustedSigningKey" value="Trusted Signing Key" /> <add key="enableMetadata" value="true" /> <add key="disableSecurity" value="false"/> </appSettings> <system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules runAllManagedModulesForAllRequests="true"> <add name="SWTModule" type="Azure.AccessControl.SecurityModule.SWTModule, Azure.AccessControl.SecurityModule" preCondition="managedHandler" /> </modules> </system.webServer>
En fonction des paramètres de sécurité, les utilisateurs de mon service peuvent être contraints à n'afficher que les métadonnées. Cette condition est extrêmement avantageuse, car les utilisateurs peuvent encore référencer les objets et propriétés d'entité dans le code, ce qui simplifie l'implémentation. Pour désactiver les métadonnées, j'ai défini l'attribut « enableMetadata » sur false pour empêcher les utilisateurs de mon service d'accéder à celles-ci. Si les utilisateurs de mon service accédaient à celui-ci uniquement via le code côté client, je n'activerais pas les métadonnées, car cela serait inutile. Le service paraît similaire à un service Web normal lorsque les métadonnées sont activées, mais ceci sans la possibilité de l'utiliser, car aucune authentification ou autorisation appropriée n'existe, comme le montre la figure 7.
Figure 7. Service OData WCF avec les métadonnées exposées
Cela fonctionne quasiment comme si Entity Framework était utilisé directement pour le code d'implémentation, moyennant quelques différences mineures. Le segment de code clé à ajouter est le jeton requis dans l'en-tête de demande lors de l'envoi des données au service OData WCF. Je vais expliquer pour l'essentiel comment le mécanisme de sécurité fonctionne. Il recherche d'abord un jeton valide dans l'en-tête et vérifie si tous ses composants sont corrects, par exemple le public ciblé, la valeur d'expiration du jeton et la valeur du jeton. Ensuite, la demande est autorisée et l'appel du service réussit. L'interception de cette demande avant le retour des données à l'utilisateur du service garantit que l'appelant du service devait obtenir un jeton valide avant de pouvoir accéder aux données.
À ce stade, selon le niveau de sécurité requis sur les objets d'entité, l'utilisateur du service peut exécuter toute fonctionnalité exposée par le service en fonction des paramètres de sécurité définis. Lorsque la sécurité n'est pas activée, l'utilisateur du service reçoit une exception qui indique que l'action effectuée n'est pas autorisée.
À la différence du code Entity Framework traditionnel, une logique supplémentaire doit être implémentée avant d'appeler le service OData sécurisé par Windows Azure. Avec le module HTTP qui protège le service, je dois veiller à m'authentifier d'abord auprès de Windows Azure et à recevoir un jeton d'accès valide avant d'appeler le service OData. Le jeton envoyé par ACS sera transmis dans l'en-tête de demande pour chaque demande effectuée au service OData sécurisé. La figure 8 illustre un exemple de demande.
Figure 8. Exemple de demande de jeton
// Request a token from ACS using (WebClient client = new WebClient()) { client.BaseAddress = string.Format("https://{0}.{1}", _accessControlNamespace, _accessControlHostName); NameValueCollection values = new NameValueCollection(); values.Add("wrap_name", wrapUsername); values.Add("wrap_password", wrapPassword); values.Add("wrap_scope", scope); byte[] responseBytes = client.UploadValues("WRAPv0.9/", "POST", values); response = Encoding.UTF8.GetString(responseBytes); Console.WriteLine("\nreceived token from ACS: {0}\n", response); }
Lorsque le jeton a été reçu de Windows Azure et que l'utilisateur a été authentifié et autorisé correctement, ACS retourne un jeton à utiliser pour toutes les demandes futures jusqu'à l'expiration de ce jeton. À ce stade, l'implémentation d'Entity Framework ressemble aux conditions dans lesquelles je suis connecté à une base de données locale ou de mon réseau. La figure 9 illustre la consommation du service OData avec un jeton d'accès.
Figure 9. Consommation du service sécurisé OData avec un jeton d'accès Windows Azure
// First things first: I obtain a token from Windows Azure _token = GetTokenFromACS(_rootURL + "NorthwindService.svc"); // Now that I have a valid token, I can call the service as needed Uri uri = new Uri(_rootURL + "NorthwindService.svc/"); try { var northwindEntities = new ODataServiceClient.NorthwindEntities(uri); // Add the event handler to send the token in my request header northwindEntities.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequest); // Sample selecting data out ... var customersFound = from customers in northwindEntities.Customers select customers; foreach (var customer in customersFound) { // custom process ... // ... <code truncated> ... } // Add new data in ... var category = oDataServiceClient.Category.CreateCategory(0, "New category"); northwindEntities.AddToCategories(category); northwindEntities.SaveChanges(); } catch (DataServiceRequestException e) { // Trap any data service exceptions such as a security error // In the event that the security does not allow an insert, // a forbidden error will be returned // ... }
Implémenter du code via le script côté client est également aussi simple que de créer un appel AJAX de mon point de terminaison de service. La figure 10 illustre la consommation du service sécurisé OData à partir d'un script côté client.
Figure 10. Consommation du service sécurisé OData à partir d'un script côté client
// Parse the entity object into JSON var jsonEntity = window.JSON.stringify(entityObject); $.support.cors = true; // Asynchronous AJAX function to create a Cateogory using OData $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", datatype: "jsonp", url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName, data: jsonEntity, beforeSend: function (XMLHttpRequest) { // Specifying this header ensures that the results will be returned as JSON XMLHttpRequest.setRequestHeader("Accept", "application/json"); XMLHttpRequest.setRequestHeader("Authorization", token); }, success: function (data, textStatus, XmlHttpRequest) { if (successCallback) { successCallback(data.d, textStatus, XmlHttpRequest); } }, error: function (XmlHttpRequest, textStatus, errorThrown) { if (errorCallback) errorCallback(XmlHttpRequest, textStatus, errorThrown); else errorHandler(XmlHttpRequest, textStatus, errorThrown); } });
Un service RESTful offre une flexibilité d'implémentation accrue et s'utilise facilement via un script Java ou d'autres scripts ou API côté client. Une authentification et un jeton sont toujours requis pour consommer le service, mais OData est standard quelle que soit la plateforme en raison de la syntaxe de requête. La figure 11 illustre la consommation du service sécurisé OData avec un jeton d'accès Windows Azure dans Java.
Figure 11. Implémentation Java de la consommation du service sécurisé OData avec un jeton d'accès Windows Azure
String serviceMethodUrl = "http://localhost/WCFDataServiceExample/NorthwindService.svc/Categories?"; GetMethod method = new GetMethod(serviceMethodUrl + "$top=1"); method.addRequestHeader("Authorization", "WRAP access_token=\"" + authToken + "\""); try { int returnCode = client.executeMethod(method); // ... <code truncated> ... br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream())); String readLine; while(((readLine = br.readLine()) != null)) { //System.err.println(readLine); result += readLine; } }
En résumé, j'éprouve souvent le besoin d'exposer les données d'une manière qui nécessite un certain niveau de sécurité pour empêcher tout accès non autorisé. L'utilisation d'ACS prend en charge cette nécessité en exploitant un service fédéré basé sur le cloud pour protéger non seulement mes services de données OData WCF mais également beaucoup d'autres applications.
Ceci dit, l'utilisation des services de données WCF seuls nécessiterait l'implémentation de contrats de données individuels et d'intercepteurs de requête pour les données à exposer. L'utilisation d'Entity Framework en association avec les services de données WCF permet d'exploiter les entités de base de données comme des contrats de données, et ces contrats sont fournis sous un format qui est déjà installé (objets sérialisables accessibles via OData). Le dernier gros morceau du casse-tête est de veiller à ce que mes services OData WCF RESTful soient protégés contre les accès non autorisés. ACS, OData et Entity Framework encapsulés par les services WCF RESTful m'offre un moyen rapide d'exposer mes données tout en utilisant une syntaxe de requête normalisée avec une couche de sécurité supplémentaire.
Sean Iannuzzi est un architecte de solutions pour The Agency Inside Harte-Hanks et tire parti des meilleures pratiques pour les solutions d'entreprise, les solutions système et les solutions logicielles. Il apprend de nouvelles technologies et recherche les moyens d'exploiter la technologie afin d'aider les entreprises et les développeurs à résoudre les problèmes. Il possède un blog sur weblogs.asp.net/seaniannuzzi et vous pouvez le suivre sur Twitter à l'adresse twitter.com/seaniannuzzi.
Merci à l'expert technique suivant d'avoir relu cet article : Danilo Diaz
Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.