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

时间:2010-03-20 04:16:26

标签: c# wcf service ado.net odata

是否有办法在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);
    }
} 

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

3 个答案:

答案 0 :(得分:5)

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

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

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

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

答案 1 :(得分:1)

看起来this video中提供的技术即使在WCF数据服务中也能正常运行。您创建了ServiceAuthorizationManager的自定义子类(请参阅MSDN),覆盖CheckAccessCore(),并在web.config中注册它。

我通过在请求的HTTP标头中传递密钥来实现它。传递给OperationContext的{​​{1}}没有为您提供获取HTTP请求标头的方法,但您可以通过CheckAccessCore获取它们。然后,您可以从该集合中获取正确的标题,然后根据需要进行检查。

以下是web.config中的必要注册:

HttpContext.Current.Request.Headers

更新:我错误地认为能够从<system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <serviceAuthorization serviceAuthorizationManagerType="FullyQualifiedTypeNameHere, ProjectNameHere" /> </behavior> </serviceBehaviors> </behaviors> 中获取标题;在IIS中运行时HttpContext.Current.Request.Headers为空(但有趣的是在调试时没有)。相反,请根据this question使用HttpContext.Current

更新2: WebOperationContext.Current.IncomingRequest.Headers仅在ASP.NET兼容模式下未运行WCF时为空。您可以通过在HttpContext.Current节点的应用程序级别将以下行添加到web.config来启用此功能:

system.serviceModel

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

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

然后你可以获得[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 以及HttpContext.Current.Request.Headers类提供的所有其他内容。

答案 2 :(得分:0)

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

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