2011-10-06 8 views
5

Estoy intentando adjuntar una clave de API a la cabecera del mensaje saliente OperationContext de la siguiente manera:Adición y recuperar los datos de solicitud de contexto

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

     } 
    } 

pero luego no tengo idea de cómo recuperar la cabecera en el lado del servidor . Estoy usando un gestor de autorización de servicio y me sale el contexto operativo actual y tratar de recuperar la cabecera de la siguiente manera:

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

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

     return prop.Headers["apikey"]; 
    } 

pero no hay cabecera apikey adjunta allí. Además, en la depuración cuando inspecciono OperationContext no puedo ver mi encabezado de apikey en ningún lado. ¿Alguien puede ver dónde me estoy equivocando?

Respuesta

14

Puede agregar encabezado personalizado de esta manera:

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

Y lado del servicio, puede obtener cabecera como:

Guid apiKey = 
OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>("apiKey", "ns"); 
+0

Gracias! ¡Descubrí que el problema que estaba teniendo era porque no estaba haciendo mi llamada de servicio durante la duración del alcance del contexto! – Dimitar

+0

¿Qué es un canal de servicio? ¿IMyServiceChannel? – PositiveGuy

+0

IMyServiceChannel es la interfaz del canal de comunicación entre el cliente y el servidor. –

1

Estoy asumiendo que tratar de consumir su servicio a través de algunos Transporte basado en protocolo Http (SOAP, REST, etc.). También estoy asumiendo que lo que desea es autorizar a la persona que llama usando la clave API suministrada. Si ambas condiciones se aplican a su pregunta, puede seguir leyendo.

Recientemente tuve que enfrentar un problema similar solo que no pasé una clave API, sino una combinación de hash de nombre de usuario/contraseña usando algunos encabezados HTTP personalizados. Finalmente lo resolví mediante la implementación de una política de autorización personalizada que una vez configurada en Web.config se enganchó bien en WCF Pipeline.

El siguiente fragmento debería ser suficiente para comenzar. Probablemente tendrías que reemplazar los encabezados x-ms-credenciales-XXX por uno solo que represente tu clave 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); 

     ... 
Cuestiones relacionadas