代码之家  ›  专栏  ›  技术社区  ›  Rush Frisby

如何在wcf数据服务中实现api密钥?

  •  4
  • Rush Frisby  · 技术社区  · 14 年前

    是否有方法要求在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中是否有$metadata,但这看起来像是一次黑客攻击。有更好的办法吗?

    3 回复  |  直到 9 年前
        1
  •  5
  •   Darrel Miller    14 年前

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

    我认为检查url中是否存在'$metadata'并没有什么问题。您正在编写服务器端代码,服务器拥有uri空间,因此基于请求url中的文本做出决策是服务器的全部功能。 你可以用这样的东西,

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

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

        2
  •  1
  •   Community CDub    7 年前

    看起来这项技术 this video 即使在wcf数据服务中也能很好地工作。您可以创建 ServiceAuthorizationManager (见 MSDN )重写 CheckAccessCore() ,并在web.config中注册。

    我通过在请求的http头中传递一个密钥来实现它。这个 OperationContext 传递给 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 按照 this question .

    更新2: HttpContext.当前 仅当未在ASP.NET兼容模式下运行WCF时为空。您可以通过在 system.serviceModel 节点:

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    

    如果除ado.net服务外还运行普通wcf服务,请在服务实现的上方添加此内容:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    

    然后你就可以 httpcontext.current.request.headers 以及所有其他由 HttpRequest 班级。

        3
  •  0
  •   Aaron Fischer    14 年前

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

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