OData

OData, Entity Framework e Controle de acesso do Windows Azure

Sean Iannuzzi

Baixar o código de exemplo

Neste artigo, mostrarei como implementar o protocolo OData (Open Data) com o Entity Framework exposto com serviços RESTful do WCF (Windows Communication Foundation) e protegido com o Windows Azure ACS (Access Control Service).

Com a maioria dos desenvolvedores, geralmente me encontro tentando utilizar uma combinação de tecnologias de novas e diversas maneiras para concluir meu projeto da maneira mais eficiente possível e ainda fornecer uma solução flexível e de fácil manutenção. Isso pode ser difícil, particularmente quando o projeto requer que os dados sejam expostos de maneira rápida e segura.

Recentemente, recebi uma solicitação para criar um serviço Web seguro para um banco de dados existente e um aplicativo Web. Eu realmente não queria implementar todo o código CRUD (criar, ler, atualizar e excluir). Era tentador apenas criar contratos de serviço personalizados, contratos de operações e de dados que controlariam exatamente como os dados poderiam ser expostos e como outras pessoas poderiam possivelmente consumir esses dados por meio de serviços. Mas eu sabia que tinha de haver um caminho mais vantajoso para seguir. Comecei pesquisando várias maneiras de se fazer isso e vi uma possibilidade com o OData (ou “Ohhhh Data”, como gosto de chamá-lo). O problema era que o OData por si só não era seguro a ponto de eu considerar aceitável, e eu precisava adicionar uma camada a mais de segurança sobre o serviço OData para ter certeza de que ele ficaria devidamente seguro. Quando comecei a juntar as peças, descobri o ACS, que é excelente para implementar um serviço de autenticação e autorização federado baseado em nuvem — exatamente o que eu precisava. Foi então que eu tive meu momento “Eureca!”. Percebi que se eu conectasse o ACS ao OData, chegaria à minha solução.

Agora, considerei implementar contratos de serviço personalizados, e há lugar para essa abordagem, especialmente onde uma camada de abstração é necessária à frente de um modelo de dados e onde é preciso proteger as entidades de bancos de dados contra a exposição direta aos consumidores de um serviço. No entanto, como isso é muito demorado — criar o documento apropriado sobre como consumir o serviço, além do esforço adicional necessário para configurar a segurança (“MessageCredential” e “TransportWithMessageCredentials”) — o projeto poderia sair rapidamente do controle. Também me preocupei com o fato de que métodos adicionais seriam necessários ou solicitados por um motivo ou outro para dar suporte à maneira como os serviços são consumidos o que, novamente, exigiria mais tempo, manutenção e personalização. Mesmo se minha implementação do serviço usasse o Entity Framework em vez do ADO.NET diretamente, criar todo o código CRUD ainda seria necessário para manter a camada de dados em sincronia. Supondo que haja algumas dúzias de tabelas, esse trabalho poderia ser extremamente entediante. E mais, criar e manter a documentação adicional e os detalhes de implementação necessários para os usuários finais consumirem meu serviço tornaram isso uma proposta muito mais complicada de administrar.

Um modo mais fácil

Depois que identifiquei as tecnologias principais, procurei outras para preencher as lacunas e ajudar a criar uma solução coesa. O objetivo era limitar a quantidade de códigos que precisariam ser gravados ou mantidos e, ao mesmo tempo, expor meus serviços OData WCF RESTful de modo seguro. As tecnologias que agrupei são: ACS, OData, Modelos de Dados de Entidade, WCF Data Services com permissões de Entidade e uma implementação de segurança personalizada do Windows Azure. Cada uma dessas tecnologias já oferece um valor significante por si só, mas quando combinadas, o valor aumenta exponencialmente. A Figura 1 demonstra uma visão geral de alto nível de como algumas dessas tecnologias funcionarão quando implementadas.


Figura 1 Visão geral de alto nível do ACS com uma interceptação de segurança

Antes de eu tentar combinar todas essas tecnologias, tive de voltar um pouco e entender realmente cada uma delas e como elas poderiam afetar esse projeto. Assim, obtive uma boa perspectiva sobre como combinar todas elas e o que seria necessário para outra pessoa consumir meus serviços usando outras tecnologias.

O que é ACS?

O ACS é fornecido como um componente da plataforma Windows Azure. O ACS permite configurar meu próprio provedor de autenticação e autorização federado baseado em nuvem que eu uso para proteger meus serviços OData WCF, e também pode ser usado para proteger qualquer aplicativo. O ACS é um serviço baseado em nuvem que ajuda a fazer uma ponte entre a lacuna de segurança quando há necessidade de implementar SSO (logon único) em vários aplicativos, serviços ou produtos — entre plataformas ou entre domínios — com suporte para várias implementações de SSO. Uma conta do Windows Azure fornece acesso a muito mais informações. Você pode se cadastrar para uma avaliação gratuita em windowsazure.com. Leia mais sobre o ACS em bit.ly/zLpIbw.

O que é OData e por que devo usá-lo?

O OData é um protocolo baseado na Web para consultar e atualizar dados, e expor os dados usando uma sintaxe padronizada. O OData usa tecnologias como HTTP, XML, JSON e o Protocolo de Publicação Atom para fornecer acesso a dados de maneira diferente. Implementar o OData com o Entity Framework e o WCF Data Services proporciona muitos benefícios excelentes.

Comecei a pensar por que eu usaria isso em vez de contratos WCF personalizados. A resposta era muito simples. O motivo mais prático era para aproveitar a documentação de serviço que já está disponível e usar uma sintaxe padronizada com suporte para o modo de acesso aos dados em meu serviço. Depois de gravar dúzias de serviços, parece que seu sempre preciso incluir mais um método em resultado do fornecimento de serviços personalizados. E os consumidores de serviços personalizados tendem a pedir cada vez mais recursos.

 Para obter mais informações sobre OData e as convenções de URI do OData, acesse os seguintes sites:

OData com o Entity Framework e o WCF Data Services

Usar o OData com o WCF Data Services e o Entity Framework expõe a funcionalidade padrão para dar suporte à recuperação e ao salvamento de dados de maneira já documentada com pouco código de implementação. Quando comecei a criar meu Modelo de Dados de Entidade para Formato de Pacote de Serviços de Dados (EDMX) e o vinculei ao meu serviço WCF por meio de serviços de dados, estava muito cético. No entanto, funcionou perfeitamente. Todas as entidades que incluí em meu EDMX era automaticamente incluídas e expostas em meu serviço WCF em uma implantação RESTful. A Figura 4 mostra alguns códigos de exemplo.

Figura 2 Implementação do OData WCF Data Services

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

Criei um EDMX e o vinculei a algumas das tabelas do meu banco de dados (Northwind Sample Database). Depois, vinculei minhas entidades de banco de dados ao meu WCF Data Service, expondo todas as entidades usando o método “SetEntitySetAccessRule” com um atributo curinga de “*” para todas as entidades. Isso me permitiu definir várias permissões em minhas entidades para acesso de leitura, gravação e consulta, bem como definir o tamanho da página, conforme ilustrado na Figura 2. O código mostrado é a implementação completa do código do OData WCF Data Services.

Os contratos de serviço, de operação e de dados são basicamente controlados pela configuração na inicialização do serviço que está sendo fornecido. No método de inicialização, pude definir várias permissões relacionadas a como gostaria de expor minhas entidades e que nível de acesso gostaria de fornecer a qualquer pessoa que quisesse consumir meus serviços. Pude até usar modelos T4 para criar uma cada abstrata ou uma camada de modelo sobre as entidades com nomes de entidade personalizados. Isso proporcionaria um nível maior de clareza para o consumidor dos meus serviços. Eu pude até definir a permissão para uma tabela específica e definir o nome da tabela juntamente com as configurações de segurança apropriadas para uma proteção de nível inferior. Este é um exemplo da concessão de acesso de leitura à tabela de cliente:

config.SetEntitySetAccessRule("Customer",
  EntitySetRights.AllRead);

Muitas implementações de segurança diferentes podem ser habilitadas com o OData e o WCF Data Services, mas agora estou preocupado apenas com a forma como proteger meus serviços WCF usando o ACS em combinação com as regras de acesso do serviço de dados.

Uma lista rápida das tecnologias usada é mostrada na Figura 3, juntamente com alguns motivos pelos quais essas tecnologias seriam usadas.

Figura 3 Tecnologias usadas e por quê

Tecnologia Por que usá-la
ACS Oferece uma maneira de proteger serviços usando um módulo de segurança federado baseado em nuvem para autenticação e autorização.
OData Fornece uma sintaxe padrão para consultar e atualizar dados, e ainda usar tecnologias comuns, como HTTP, JSON, o Protocolo de Publicação Atom e XML
Modelos de Dados de Entidade Fornecem uma maneira rápida de criar acesso a dados comuns para uma camada de banco de dados e ainda fornecer contratos de dados serializáveis de tabelas em um banco de dados.
WCF Data Services com Permissões de Entidade Expõe o contrato de dados do Entity Framework com o nível apropriado de permissões para CRUD como serviço WCF RESTful
Implementação de Segurança Personalizada do Windows Azure Protege serviços (nesse caso, serviços OData) contra o consumo sem o nível adequado de segurança ser aplicado, como token ou certificado.

Com cada uma dessas tecnologias há sempre compensações com base no projeto, mas descobri que combiná-las me poupou muito tempo de configuração antecipada e reduziu os trabalhos de manutenção, além de exigir menos código e fornecer vantagens enormes — especialmente quando precisei expor meus dados de maneira segura e fornecer métodos comuns de acesso a dados com uma sintaxe padronizada.

Unindo todos os elementos

Com um entendimento razoavelmente bom do uso combinado de OData, Entity Framework e WCF Data Services, consegui aplicar alguns recursos de segurança adicionais a essa tecnologia usando o ACS. Havia algumas opções para proteger meu serviço contra o acesso, inclusive definir várias permissões nas entidades ou adicionar interceptores de consulta para impedir o consumo do serviço ou controlar como meu serviço poderia ser consumido.

No entanto, implementar interceptores de consulta ou definir permissões seria entediante, e era preferível incluir uma camada de segurança sobre meu serviço para protegê-lo contra o consumo para impedir o consumo do serviço em vez de gravar um código adicional. Implementar um mecanismo de segurança comum que permite que pessoas confiáveis ou empresas externas acessem meus serviços seria o ideal. Por sua vez, eu poderia usar uma combinação dessa segurança com a proteção de entidade para dar aos meus serviços a implementação mais segura com a máxima flexibilidade.

Usar essa abordagem exigiria que o consumidor do meu serviço se autenticasse primeiro no ACS para obter um token de acesso válido. Os serviços seriam restritos sem esse token de acesso. Tokens de acesso válidos seriam necessários no cabeçalho de solicitação antes de a pessoa receber permissão para acessar meu serviço. Uma vez autorizado o consumidor do meu serviço, eu aplicaria uma segurança rígida nas entidades para garantir somente o acesso autorizado aos dados ou às minhas entidades.

Instalação e configuração do ACS

Certa instalação e configuração é necessária para implementar o ACS. A Figura 4 mostra uma lista de itens que instalei para esse exemplo.

Figura 4 Instalação do ACS

Configuração Valores
Namespace ACS WCFoDataACS
Aplicativo de terceira parte confiável

Nome: wcfodataacsexampleDevelopment

Modo: Mantenha os padrões (insira as configurações manualmente)

Realm: http://localhost/WCFDataServiceExample/<servicename>.svc

URL de retorno: Mantenha o padrão (em branco)

URL de erro: Mantenha o padrão (em branco)

Formato do token: SWT

Política de criptografia do token: Mantenha o padrão (nenhum)

Duração do token: Mantenha o padrão (600)

Configurações de autenticação

Provedores de identidade: Desmarque Windows Live ID

Grupo de regras: Selecione Criar Novo Grupo de Regras

Observação: Criei configurações diferentes para desenvolvimento, teste e produção.

Configurações de autenticação do token

Clique no botão Gerar

Data de início de vigência: Mantenha os padrões

Data de validade: Mantenha os padrões

Grupo de regras Observação: Baseado nas minhas configurações, o grupo de regras será criado automaticamente, mas ainda precisarei adicionar a configuração de solicitação.
Configuração de solicitação

Seção If:

Sistema de controle de acesso: Selecionado

Tipo de solicitação de entrada: Mantenha o padrão (qualquer um)

Valor de solicitação de entrada: Mantenha o padrão (qualquer um)

Seção Then:

Tipo de solicitação de saída: Mantenha o padrão (passar por tipo de solicitação de entrada)

Valor de solicitação de saída: Mantenha o padrão (passar por valor de solicitação de entrada)

Informações da regra:

Descrição: Mantenha o padrão ou digite uma descrição

Identidade do serviço no Windows

Nome: o nome de usuário a ser fornecido a outros (neste exemplo, usei wcfodataacsDevUser)

Descrição: Mantenha os padrões (ou digite uma descrição para o usuário)

Realm: http://localhost/WCFDataServiceExample/<servicename>.svc

Configurações de credencial:

Tipo: Selecionar senha

Senha: Digite a senha desejada

Data de início de vigência: Mantenha os padrões

Data de validade: Mantenha os padrões

Observação: Há várias opções sobre como autenticar um usuário nos serviços criados, mas para simplificar as coisas, usei uma entrada de senha como tipo de credencial. Há outras opções disponíveis — como usar um certificado x509 ou uma chave simétrica — que pode fornecer um nível maior de segurança, mas neste exemplo, tentei manter o básico.

Depois de concluir a instalação do ACS, consegui proteger meus serviços OData WCF RESTFul. Antes de poder protegê-los, tive de implementar primeiro um módulo de segurança personalizado que pudesse interceptar as solicitações e validar a segurança para evitar o acesso não autorizado.

Implementação de segurança do ACS

Como exemplo, implementei a segurança usando um módulo HTTP personalizado. Isso intercepta qualquer solicitação feita para meu serviço e valida se ocorreu a autenticação e a autorização adequadas. Sem esse módulo HTTP, meus serviços seriam seguros somente no nível de entidade, baseado nos parâmetros da configuração do serviço de dados.

Nesse caso, protegi esses serviços com o ACS; portanto, as solicitações eram interceptadas e verificadas em relação ao nível adequado de segurança para garantir que o consumidor do serviço tenha recebido o nível de autorização adequado. Como dito anteriormente, uma segurança rígida poderia ser implementada no nível de entidade depois de o consumidor do serviço ser autorizado a acessar.

Ao implementar a interface IHTTPModule, optei por adicionar alguns recursos. Então, expus partes dos metadados do serviço para permitir que os consumidores do serviços gerem classes automaticamente (similar ao comportamento de adicionar qualquer outro serviço Web). Adicionei essas seções de código como atributos configuráveis que podem ser habilitados ou desabilitados para maior segurança, testar e facilitar o trabalho de integração.

A Figura 5 mostra o código que intercepta as solicitações e executa a validação de segurança adequada.

Figura 5 Validação de segurança

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> ...
        }
      }
    }
  }
}

SDK do Windows Azure

Extraí uma classe do SDK do Windows Azure para executar validações de token para essa implementação. O projeto pode ser encontrado em bit.ly/utQd3S. Depois de instalar o SDK, copiei o arquivo chamado “tokenvalidator.cs” em um novo projeto. Nessa classe específica, chamei o método de validação para determinar se o usuário foi autorizado pelas informações configuradas no ACS. Para simplificar essa implementação, criei um DLL personalizado somente com o mecanismo de segurança necessário. Depois de criar o assembly, tudo que eu precisava era uma referência para a DLL de segurança com meu serviço OData WCF. O resultado uma implementação protegida e segura.

Implementação do serviço OData seguro

Com o aprimoramento de segurança adicional implantado, proteger o serviço OData WCF ficou fácil. Tudo que eu precisava era de uma referência ao assembly “Azure.AccessControl.SecurityModule” e incluí-la aos parâmetros de configuração adicionais. Em seguida, os recursos de segurança seriam habilitados. A Figura 6 mostra os parâmetros de configuração de segurança.

Figura 6 Parâmetros de configuração de segurança

<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>

Dependendo das configurações de segurança, os consumidores do meu serviço poderiam ficar restritos a ver apenas os metadados. Isso é extremamente benéfico porque os usuários ainda podem fazer referência aos objetos e propriedades de entidade no código, simplificando a implementação. Para desabilitar os metadados, defini o atributo “enableMetadata” como false, para que os consumidores do meu serviço não pudessem mais acessar os metadados. Se os consumidores do meu serviços acessassem somente via código de cliente, eu não habilitaria os metadados porque não seria necessário. O serviço parece um serviço Web normal quando os metadados são habilitados, mas sem a capacidade de consumi-lo sem a devida autenticação e autorização, conforme mostrado na Figura 7.


Figura 7 Serviço OData WCF com metadados expostos

Isso funciona quase da mesma forma que usar o Entity Framework diretamente no código de implementação, com diferenças sutis. O segmento do código principal a ser adicionado é o token solicitado no cabeçalho da solicitação ao enviar os dados para o serviço OData WCF. Explicarei como o mecanismo de segurança funciona, em essência. Primeiro, ele verifica se há um token válido no cabeçalho e se todos os componentes estão OK, como o público-alvo, a validade e o valor do token. Em seguida, a solicitação é autorizada e a chamada para o serviço é bem-sucedida. Interceptar essa solicitação antes de retornar dados ao consumidor do serviço verifica se o chamador do serviço teve de obter um token válido antes de ser autorizado a acessar os dados.

Nesse momento — dependendo do nível de segurança exigido nos objetos de entidade — o consumidor do serviço pode executar qualquer funcionalidade exposta pelo serviço com base nas configurações de segurança definidas. Quando a segurança não está habilitada, o consumidor do serviço recebe uma exceção que indica se a ação executada não é permitida.

Diferente do código tradicional do Entity Framework, é preciso implementar mais lógica antes de chamar o serviço OData protegido pelo Windows Azure. Com o módulo HTTP protegendo o serviço, preciso me certificar de autenticar primeiro no Windows Azure e receber um token de acesso válido antes de chamar o serviço OData. O token recebido do ACS passará pelo cabeçalho de solicitação para cada solicitação feita ao serviço OData protegido. A Figura 8 mostra um exemplo de solicitação.

Figura 8 Exemplo de solicitação de token

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

Uma vez recebido o token do Windows Azure e o usuário autenticado e autorizado com sucesso, um token será retornado pelo ACS para usar em todas as solicitações futuras até expirar. Nesse ponto, implantar o Entity Framework é quase o mesmo que estar conectado a um banco de dados local ou a um banco de dados em minha rede. A Figura 9 mostra o consumo do serviço OData com um token de acesso.

Figura 9 Consumo do serviço OData protegido com um token de acesso do 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
  // ...
}

Implementar o código via script de cliente é tão fácil quanto efetuar uma chamada AJAX para o ponto de extremidade do meu serviço. A Figura 10 mostra o consumo do serviço OData protegido usando o script de cliente.

Figura 10 Consumo do serviço OData protegido usando o script de cliente

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

Um serviço RESTful fornece mais flexibilidade de implementação e é facilmente consumido via Java ou outros scripts ou APIs de cliente. A autenticação e um token ainda são necessários para consumir o serviço, mas o OData é padrão independentemente da plataforma devido à sintaxe de consulta. A Figura 11 mostra o consumo do serviço OData protegido com um token de acesso do Windows Azure em Java.

Figura 11 Implementação Java do consumo do serviço OData protegido com um token de acesso do 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;
  }
}

Para resumir, geralmente tenho a necessidade de expor dados de maneira que exija certo nível de segurança para evitar o acesso não autorizado. Usar o ACS dá suporte a essa necessidade usando um serviço federado baseado na nuvem para proteger não só meu OData WCF Data Services, como também muitos outros aplicativos.

Dito isso, usar o WCF Data Services isoladamente exigiria a implementação de contratos de dados e interceptores individuais para os dados serem expostos. Usar o Entity Framework em combinação com o WCF Data Services fornece a capacidade de usar entidades de bancos de dados como contratos de dados — e esses contratos são fornecidos em formato já configurado (objetos serializáveis acessíveis via OData). A última peça do quebra-cabeça é garantir que meus serviços OData WCF RESTful sejam protegidos contra o acesso não autorizado. Usar o ACS, o OData e o Entity Framework combinados pelos serviços WCF RESTful oferece uma maneira rápida de expor meus dados e ainda usar uma sintaxe de consulta padrão com uma camada adicional de segurança.

Sean Iannuzzi é arquiteto de soluções da The Agency Inside Harte-Hanks, que usa práticas recomendadas para criar soluções para empresas, sistemas e software. Ele adora aprender novas tecnologias e encontrar maneiras de usar a tecnologia para ajudar empresas e desenvolvedores na solução de problemas. Ele mantém um blog em weblogs.asp.net/seaniannuzzi, e você pode segui-lo no Twitter em acompanhá-lo em twitter.com/seaniannuzzi.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Danilo Diaz