Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding and Retrieving data from request context

I'm trying to attach an api key to the OperationContext outgoing message header as follows:

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

        }
    }

but then I have no idea how to retrieve the header on the server side. I'm using a Service authorisation manager and I get the current operating context and try to retrieve the header like this:

    public string GetApiKey(OperationContext operationContext)
    {
        var request = operationContext.RequestContext.RequestMessage;

        var prop = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];

        return prop.Headers["apikey"];
    }

but there is no apikey header attached there. Also, on debugging when I inspect the operationContext I cant seem to see my apikey header anywhere. Can anyone see where I'm going wrong?

like image 797
Dimitar Avatar asked Oct 06 '11 05:10

Dimitar


People also ask

What is the context of a request?

The request context keeps track of the request-level data during a request. Rather than passing the request object to each function that runs during a request, the request and session proxies are accessed instead.

What is request context in Java?

public class RequestContext extends Object. Context holder for request-specific state, like current web application context, current locale, current theme, and potential binding errors. Provides easy access to localized messages and Errors instances.


2 Answers

You can add custom header by this way :

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(...);
          }
       }                    
    }

And service side, you can get header like :

Guid apiKey = 
OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>("apiKey", "ns");
like image 156
Upendra Chaudhari Avatar answered Oct 01 '22 15:10

Upendra Chaudhari


I'm assuming that you trying to consume your service using some Http Protocol based transport (SOAP, REST etc). I'm also assuming that what you want is to authorize the caller using the supplied API key. If both of those conditions apply to your question, you can read on.

I recently had to tackle a similar problem only that I did not pass an API key but a username/password hash combination using some HTTP custom headers. I ultimately solved it by implementing a custom authorization policy that once configured in Web.config hooked nicely into the WCF Pipeline.

The snippet below should be enough to get you started. You probably would have to replace the x-ms-credentials-XXX headers by a single one representing your API key.

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

        ...
like image 28
Oliver Weichhold Avatar answered Oct 01 '22 16:10

Oliver Weichhold