您将如何在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头中传递密钥来使其工作。 传递给CheckAccessCore
的OperationContext
没有为您提供获取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.Headers
和HttpRequest
类提供的所有其他东西。
您可以检查请求类型,并通过api密钥让wsdl调用完成。
我不确定你的api目标是什么,但你可以使用客户端证书。