如何在 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);
}
}
...这可以工作,但并不完美,因为您无法通过“添加服务引用”资源管理器获取元数据并发现服务。我可以检查 $metadata 是否在 url 中,但这看起来像是一个 hack。有更好的办法吗?
Is there a way to require an API key in the URL / or some other way of passing the service a private key in order to grant access to the data?
I have this right now...
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);
}
}
...This works but it's not perfect because you cannot get at the metadata and discover the service through the Add Service Reference explorer. I could check if $metadata is in the url but it seems like a hack. Is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议使用授权标头来传递 apiKey,而不是在查询字符串中传递它。这就是它的用途,它有助于将 api 密钥排除在日志文件之外。
我不认为检查 url 中是否存在“$metadata”有什么问题。您正在编写服务器端代码,并且服务器拥有 URI 空间,因此根据请求 url 中的文本做出决策就是服务器的全部内容。
你可以使用类似的东西,
而不是搜索整个 uri 字符串,如果它能让你感觉不那么恶心的话!
I would suggest using the authorization header to pass the apiKey instead of passing it in the query string. That's what it is there for and it help's to keep api keys out of log files.
I don't think there is anything really wrong with checking for the presence of '$metadata' in the url. You are writing the server side code, and the server owns the URI space, so making decisions based on text in the request url is what the server is all about.
You could use something like,
instead of searching the entire uri string, if it makes it feel less icky!
看起来像 该视频 即使在 WCF 数据服务中也能正常工作。您创建
ServiceAuthorizationManager
的自定义子类(请参阅 MSDN),覆盖CheckAccessCore()
,并在 web.config 中注册它。我通过在请求的 HTTP 标头中传递密钥来使其工作。传递给
CheckAccessCore
的OperationContext
并没有为您提供获取 HTTP 请求标头的方法,但您可以通过HttpContext.Current.Request 获取它们.标题
。然后,您可以从该集合中获取正确的标头,并根据需要进行检查。以下是 web.config 中必要的注册:
更新:关于能够从
HttpContext.Current.Request.Headers
获取标头,我错了;在 IIS 中运行时,HttpContext.Current
为 null(但有趣的是,在调试时不是)。相反,请按照此问题使用WebOperationContext.Current.IncomingRequest.Headers
。更新2:
HttpContext.Current
仅当您未在 ASP.NET 兼容模式下运行 WCF 时才为 null。您可以通过在system.serviceModel
节点的应用程序级别将以下行添加到 web.config 来打开此功能:如果您正在运行普通的 WCF 服务,还可以将其添加到服务的实现之上除了 ADO.NET 服务之外:
然后您可以获得 HttpContext.Current.Request.Headers 以及 HttpRequest 类提供的所有其他内容。
Looks like the technique presented in this video works well even in WCF Data Services. You create a custom subclass of
ServiceAuthorizationManager
(see MSDN), overrideCheckAccessCore()
, and register it in web.config.I got it to work by passing a key in a HTTP header of the request. The
OperationContext
passed toCheckAccessCore
doesn't give you a way to grab the HTTP Request headers, but you can get them viaHttpContext.Current.Request.Headers
. You can then get the proper header out of that collection and check it however you need to.Here is the necessary registration in web.config:
UPDATE: I was wrong about being able to get headers out of
HttpContext.Current.Request.Headers
;HttpContext.Current
is null when running in IIS (but interestingly not when debugging). Instead, useWebOperationContext.Current.IncomingRequest.Headers
as per this question.UPDATE 2:
HttpContext.Current
is only null when you're not running WCF in ASP.NET Compatibility mode. You can turn this on by adding the following line to web.config at the application level in thesystem.serviceModel
node:Also add this above the implementation of your service, if you have a vanilla WCF service running in addition to the ADO.NET service:
Then you can get
HttpContext.Current.Request.Headers
and all the other stuff provided by theHttpRequest
class.您可以检查请求类型并让 wsdl 调用在没有 api 密钥的情况下进行。
我不确定你的 api 目标是什么,但你可以使用客户端证书。
You can check the request type and let wsdl calls go through with out the api key.
I am not sure what your api goals are but you could use a client certificate.