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

Posted

技术标签:

【中文标题】从请求上下文中添加和检索数据【英文标题】:Adding and Retrieving data from request context 【发布时间】:2011-12-02 00:13:24 【问题描述】:

我正在尝试将 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 标头。谁能看出我哪里出错了?

【问题讨论】:

【参考方案1】:

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

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");

【讨论】:

谢谢!我发现我遇到的问题是因为我没有在上下文范围的生命周期内进行服务调用! 什么是服务渠道? IMyServiceChannel? IMyServiceChannel 是客户端和服务器之间的通信通道接口。 IMyServiceChannel的定义在哪里?【参考方案2】:

我假设您尝试使用一些基于 Http 协议的传输(SOAP、REST 等)来使用您的服务。我还假设您想要使用提供的 API 密钥授权调用者。如果这两个条件都适用于您的问题,您可以继续阅读。

我最近不得不解决一个类似的问题,只是我没有传递 API 密钥,而是使用一些 HTTP 自定义标头传递用户名/密码哈希组合。我最终通过实现一个自定义授权策略解决了这个问题,该策略曾经在 Web.config 中配置,很好地连接到 WCF 管道中。

下面的 sn-p 应该足以让您入门。您可能必须将 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);

        ...

【讨论】:

【参考方案3】:

您是否看过这个问题:How to add a custom HTTP header to every WCF call??它可能包含您的解决方案。

【讨论】:

是的,我看过了,我想尝试保留服务身份验证管理器,因为它正是我需要的。

以上是关于从请求上下文中添加和检索数据的主要内容,如果未能解决你的问题,请参考以下文章

寄存器如何在上下文切换中快速存储和检索数据?

从核心数据中保存和检索数据

从尚未提交的上下文中获取数据。核心数据

当 `this` 不可用时,从拖动回调中检索 DOM 目标

检索数据服务器端并使用 Next.js 保存在上下文中

如何从视图中的上下文对象中检索对象或特定字段?