C# 从请求上下文添加和检索数据

C# 从请求上下文添加和检索数据,c#,wcf,asp.net-mvc-3,C#,Wcf,Asp.net Mvc 3,我正在尝试将api密钥附加到OperationContext传出消息头,如下所示: public static void AddApikeyToHeader(string apikey, IContextChannel channel, string address) { using (OperationContextScope scope = new OperationContextScope(channel)) { Me

我正在尝试将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头。有人知道我错在哪里吗?

你看了这个问题吗:?它可能包含您的解决方案。

您可以通过以下方式添加自定义标题:

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(...);
          }
       }                    
    }
使用(ChannelFactory工厂=
新的ChannelFactory(新的NetTcpBinding())
{
使用(IMyServiceChannel proxy=factory.CreateChannel(…)
{
使用(OperationContextScope范围=新OperationContextScope(代理))
{
Guid apiKey=Guid.NewGuid();
MessageHeader mhg=新的MessageHeader(apiKey);
MessageHeader untyped=mhg.GetUntypedHeader(“apiKey”,“ns”);
OperationContext.Current.OutgoingMessageHeaders.Add(非类型化);
代理操作(…);
}
}                    
}
在服务端,您可以得到如下标题:

Guid apiKey = 
OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>("apiKey", "ns");
Guid-apiKey=
OperationContext.Current.IncomingMessageHeaders.GetHeader(“apiKey”、“ns”);

我假设您试图使用一些基于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);

        ...
内部类重新授权策略:IAAuthorizationPolicy
{
公共重新授权策略()
{
Id=Guid.NewGuid().ToString();
发卡机构=索赔集。系统;
}
public bool Evaluate(EvaluationContext EvaluationContext,ref对象状态)
{
常量字符串HttpRequestKey=“httpRequest”;
const String UsernameHeaderKey=“x-ms-credentials-username”;
const String PasswordHeaderKey=“x-ms-credentials-password”;
常量字符串identieskey=“identies”;
常量字符串PrincipalKey=“Principal”;
//检查上下文的属性是否具有标识列表
如果(evaluationContext.Properties.Count>0||
evaluationContext.Properties.ContainsKey(IdentitiesKey)||
!OperationContext.Current.IncomingMessageProperties.ContainsKey(HttpRequestKey))
返回false;
//获取http请求
var httpRequest=(HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpRequestKey];
//提取凭证
var username=httpRequest.Headers[UsernameHeaderKey];
var password=httpRequest.Headers[PasswordHeaderKey];
//验证凭据是否完整
if(string.IsNullOrEmpty(用户名)| | string.IsNullOrEmpty(密码))
返回false;
//获取或创建标识列表
如果(!evaluationContext.Properties.ContainsKey(IdentitiesKey))
evaluationContext.Properties[IdentitiesKey]=新列表();
var identies=(List)evaluationContext.Properties[identieskey];
//查找用户
使用(var con=ServiceLocator.Current.GetInstance())
{
使用(var userDao=ServiceLocator.Current.GetDao(con))
{
var user=userDao.GetUserByUsernamePassword(用户名,密码);
...

是的,我看了一下,我想尝试保留service authentication manager,因为这正是我需要的。谢谢!我发现了我遇到的问题,因为我在上下文作用域的生命周期内没有进行服务调用!什么是服务通道?IMyServiceChannel?IMyServiceChannel是通信通道int客户端和服务器之间的接口。
IMyServiceChannel
的定义在哪里?