我正在尝试将api密钥附加到OperationContext传出邮件头,如下所示:
public static void AddApikeyToHeader(string apikey, IContextChannel channel, string address)
{
using (OperationContextScope scope = new OperationContextScope(channel))
{
MessageHeader header = MessageHeader.CreateHeader("apikey", address, apikey);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
}
}
但后来我不知道如何在服务器端检索标头。我正在使用服务授权管理器,我得到当前的操作上下文并尝试检索这样的标题:
public string GetApiKey(OperationContext operationContext)
{
var request = operationContext.RequestContext.RequestMessage;
var prop = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
return prop.Headers["apikey"];
}
但那里没有apikey标题。另外,在我检查operationContext的时候调试我似乎无法在任何地方看到我的apikey头。谁能看到我哪里出错?
答案 0 :(得分:14)
您可以通过以下方式添加自定义标头:
using (ChannelFactory<IMyServiceChannel> factory =
new ChannelFactory<IMyServiceChannel>(new NetTcpBinding()))
{
using (IMyServiceChannel proxy = factory.CreateChannel(...))
{
using ( OperationContextScope scope = new OperationContextScope(proxy) )
{
Guid apiKey = Guid.NewGuid();
MessageHeader<Guid> mhg = new MessageHeader<Guid>(apiKey);
MessageHeader untyped = mhg.GetUntypedHeader("apiKey", "ns");
OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
proxy.DoOperation(...);
}
}
}
在服务方面,您可以获得如下标题:
Guid apiKey =
OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>("apiKey", "ns");
答案 1 :(得分:1)
我假设您尝试使用基于Http协议的传输(SOAP,REST等)来使用您的服务。我还假设你想要的是使用提供的API密钥授权调用者。如果这两个条件都适用于您的问题,您可以继续阅读。
我最近不得不解决类似的问题,只是我没有传递API密钥,而是使用一些HTTP自定义标头的用户名/密码哈希组合。我最终通过实现一个自定义授权策略解决了这个问题,该策略曾经在Web.config中配置好,很好地挂钩到WCF管道。
下面的代码段应该足以让您入门。您可能需要将x-ms-credentials-XXX标头替换为代表您的API密钥的单个标头。
internal class RESTAuthorizationPolicy : IAuthorizationPolicy
{
public RESTAuthorizationPolicy()
{
Id = Guid.NewGuid().ToString();
Issuer = ClaimSet.System;
}
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
const String HttpRequestKey = "httpRequest";
const String UsernameHeaderKey = "x-ms-credentials-username";
const String PasswordHeaderKey = "x-ms-credentials-password";
const String IdentitiesKey = "Identities";
const String PrincipalKey = "Principal";
// Check if the properties of the context has the identities list
if (evaluationContext.Properties.Count > 0 ||
evaluationContext.Properties.ContainsKey(IdentitiesKey) ||
!OperationContext.Current.IncomingMessageProperties.ContainsKey(HttpRequestKey))
return false;
// get http request
var httpRequest = (HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpRequestKey];
// extract credentials
var username = httpRequest.Headers[UsernameHeaderKey];
var password = httpRequest.Headers[PasswordHeaderKey];
// verify credentials complete
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
return false;
// Get or create the identities list
if (!evaluationContext.Properties.ContainsKey(IdentitiesKey))
evaluationContext.Properties[IdentitiesKey] = new List<IIdentity>();
var identities = (List<IIdentity>) evaluationContext.Properties[IdentitiesKey];
// lookup user
using (var con = ServiceLocator.Current.GetInstance<IDbConnection>())
{
using (var userDao = ServiceLocator.Current.GetDao<IUserDao>(con))
{
var user = userDao.GetUserByUsernamePassword(username, password);
...
答案 2 :(得分:0)
您是否看过这个问题:How to add a custom HTTP header to every WCF call??它可能包含您的解决方案。