Pergunta

Existe uma maneira de exigir uma chave da API no URL / ou em alguma outra maneira de passar ao serviço uma chave privada para conceder acesso aos dados?

Eu tenho isso agora ...

using System;
using System.Data.Services;
using System.Data.Services.Common;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Web;
using Numina.Framework;
using System.Web;
using System.Configuration;

[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class odata : DataService {


    public static void InitializeService(DataServiceConfiguration config) {

        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        //config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }

    protected override void OnStartProcessingRequest(ProcessRequestArgs args) {

        HttpRequest Request = HttpContext.Current.Request;
        if(Request["apikey"] != ConfigurationManager.AppSettings["ApiKey"])
            throw new DataServiceException("ApiKey needed");

        base.OnStartProcessingRequest(args);
    }
} 

... Isso funciona, mas não é perfeito, porque você não pode chegar aos metadados e descobrir o serviço através do Explorer de Referência de Serviço Add Service. Eu poderia verificar se $ metadados está no URL, mas parece um hack. Existe uma maneira melhor?

Foi útil?

Solução

Eu sugeriria o uso do cabeçalho da autorização para passar o apikey em vez de passá -lo na sequência de consultas. É para isso que existe e ajuda a manter as teclas da API fora dos arquivos de log.

Eu não acho que há algo realmente errado em verificar a presença de '$ metadados' no URL. Você está escrevendo o código do servidor e o servidor possui o espaço URI, portanto, tomar decisões com base no texto na URL da solicitação é o que é o servidor. Você poderia usar algo como,

  if (requestUrl.Segments.Last().Replace('/','') != '$metadata') 

Em vez de pesquisar toda a corda URI, se ela se sentir menos nojenta!

Outras dicas

Parece a técnica apresentada em esse vídeo Funciona bem mesmo em serviços de dados da WCF. Você cria uma subclasse personalizada de ServiceAuthorizationManager (Vejo Msdn), sobrepor CheckAccessCore(), e registre -o em web.config.

Consegui funcionar passando uma chave em um cabeçalho HTTP da solicitação. o OperationContext passado para CheckAccessCore não lhe dá uma maneira de pegar os cabeçalhos de solicitação HTTP, mas você pode obtê -los via HttpContext.Current.Request.Headers. Você pode obter o cabeçalho adequado dessa coleção e verificá -lo como precisar.

Aqui está o registro necessário em web.config:

<system.serviceModel>
  <behaviors>
      <serviceBehaviors>
          <behavior>
              <serviceAuthorization serviceAuthorizationManagerType="FullyQualifiedTypeNameHere, ProjectNameHere" />
          </behavior>
      </serviceBehaviors>
  </behaviors>

ATUALIZAR: Eu estava errado em poder tirar cabeçalhos de HttpContext.Current.Request.Headers; HttpContext.Current é nulo ao executar no IIS (mas curiosamente não quando depurar). Em vez disso, use WebOperationContext.Current.IncomingRequest.Headers conforme essa questão.

Atualização 2: HttpContext.Current é apenas nulo quando você não está executando o WCF no modo de compatibilidade do ASP.NET. Você pode ativar isso adicionando a seguinte linha ao web.config no nível do aplicativo no system.serviceModel nó:

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

Adicione também isso acima da implementação do seu serviço, se você tiver um serviço WCF de baunilha em execução, além do serviço ADO.NET:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

Então você pode conseguir HttpContext.Current.Request.Headers e todas as outras coisas fornecidas pelo HttpRequest classe.

Você pode verificar o tipo de solicitação e deixar as chamadas WSDL passarem com a tecla API.

Não tenho certeza de quais são seus objetivos da API, mas você pode usar um certificado de cliente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top