是否有办法在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);
}
}
...这可行,但它并不完美,因为您无法获取元数据并通过“添加服务引用”资源管理器发现服务。我可以检查$元数据是否在网址中,但它似乎是一个黑客。还有更好的方法吗?
答案 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目标是什么,但您可以使用客户端证书。