5

有没有办法在 URL 中要求 API 密钥 / 或以其他方式向服务传递私钥以授予对数据的访问权限?

我现在有这个...

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

...这可行,但并不完美,因为您无法通过“添加服务引用”资源管理器获取元数据并发现服务。我可以检查 $metadata 是否在 url 中,但这似乎是一个 hack。有没有更好的办法?

4

3 回答 3

5

我建议使用授权标头来传递 apiKey 而不是在查询字符串中传递它。这就是它的用途,它有助于将 api 密钥保留在日志文件之外。

我认为检查 url 中是否存在“$metadata”并没有什么问题。您正在编写服务器端代码,并且服务器拥有 URI 空间,因此根据请求 url 中的文本做出决策就是服务器的全部内容。你可以使用类似的东西,

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

而不是搜索整个 uri 字符串,如果它让它感觉不那么恶心!

于 2010-03-20T12:46:07.947 回答
1

看起来这个视频中介绍的技术即使在 WCF 数据服务中也能很好地工作。您创建一个自定义子类ServiceAuthorizationManager(请参阅MSDN)、覆盖CheckAccessCore()并在 web.config 中注册它。

我通过在请求的 HTTP 标头中传递一个密钥来使其工作。OperationContext传递的 to不能CheckAccessCore让您获取 HTTP 请求标头,但您可以通过HttpContext.Current.Request.Headers. 然后,您可以从该集合中获取正确的标题并根据需要进行检查。

这是 web.config 中必要的注册:

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

更新:我错了能够从HttpContext.Current.Request.Headers;中获取标题。HttpContext.Current在 IIS 中运行时为空(但有趣的是在调试时不是)。相反,WebOperationContext.Current.IncomingRequest.Headers按照这个问题使用。

UPDATE 2: HttpContext.Current只有当您不在 ASP.NET 兼容模式下运行 WCF 时才为空。您可以通过将以下行添加到system.serviceModel节点中应用程序级别的 web.config 来启用此功能:

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

如果除了 ADO.NET 服务之外还有一个普通的 WCF 服务正在运行,那么还要在服务的实现上面添加这个:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

然后,您可以获得HttpContext.Current.Request.Headers该课程提供的所有其他内容HttpRequest

于 2012-05-30T20:09:18.440 回答
0

您可以检查请求类型并让 wsdl 调用在没有 api 密钥的情况下通过。

我不确定您的 api 目标是什么,但您可以使用客户端证书。

于 2010-03-20T04:32:13.170 回答