您将如何在WCF数据服务中实现API密钥?

有没有办法要求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); } } 

…这有效,但它并不完美,因为您无法通过添加服务参考资源管理器获取元数据并发现服务。 我可以检查$元数据是否在url中,但它似乎是一个黑客。 有没有更好的办法?

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

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

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

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

看起来这个video中提供的技术即使在WCF数据服务中也能很好地工作。 您创建ServiceAuthorizationManager的自定义子类(请参阅MSDN ),重写CheckAccessCore() ,并在web.config中注册它。

我通过在请求的HTTP头中传递密钥来使其工作。 传递给CheckAccessCoreOperationContext没有为您提供获取HTTP请求标头的方法,但您可以通过HttpContext.Current.Request.Headers获取它们。 然后,您可以从该集合中获取正确的标题,然后根据需要进行检查。

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

         

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

更新2:当您在ASP.NET兼容模式下未运行WCF时, HttpContext.Current仅为null。 您可以通过在system.serviceModel节点中的应用程序级别将以下行添加到web.config来启用此function:

  

如果除了ADO.NET服务之外还运行了一个vanilla WCF服务,还要在服务实现之上添加:

 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 

然后你可以得到HttpContext.Current.Request.HeadersHttpRequest类提供的所有其他东西。

您可以检查请求类型,并通过api密钥让wsdl调用完成。

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