2010-09-02 16 views
6

que necesito para pasar un valor de cliente cada vez que una solicitud enviada a WCF y comprobar que el valor en el servidor y decidir hacer la solicitud o no, cualquiera puede escribir un ejemplo de eso? No estoy seguro de cómo es que va a implementarseWCF y autenticación

caso: im generar una clave basada en el hardware del cliente y quiero enviar esa clave al servidor con cada solicitud para verificar si la clave es aceptada en el servidor db y luego decidir procesar la solicitud o no.

gracias de antemano.

+1

Ver http://stackoverflow.com/questions/964433/how-to-add-a-custom-header-to-every-wcf-calls para pasar automáticamente los datos como un encabezado. Sin embargo, no sé cómo verificarlo automáticamente en el servidor, pero espero que haya un gancho. – Rup

Respuesta

1

primer lugar tenemos que poner en práctica el comportamiento y el inspector en el lado del cliente para enviar clave para autenticar al cliente:

class AuthenticationBehaviour : IEndpointBehavior 
{ 
    #region IEndpointBehavior Members 

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
    { 
     AuthenticationMessageInspector inspector = new AuthenticationMessageInspector(); 
     clientRuntime.MessageInspectors.Add(inspector); 
    } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
    { 
     //AuthenticationMessageInspector inspector = new AuthenticationMessageInspector(); 
     //endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector); 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
    } 

    class AuthenticationMessageInspector : IClientMessageInspector 
{ 
    private const string HeaderKey = "Authentication"; 

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 

     if (Session.MachineId == 0) 
     { 
      Session.MachineId = LicenseGenerator.GenerateLicense(); 
     } 


     request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, Session.MachineId)); 
     return null; 
    } 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { 

    } 
} 

Ahora tenemos que poner en práctica el comportamiento y el inspector en el lado del servidor (servicio WCF) a inspeccionar cada petición realizada y extraer la cabecera y luego validarlo:

public class AuthenticationBehaviour : IEndpointBehavior 
{ 
    #region IEndpointBehavior Members 

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
    { 
     //AuthenticationMessageInspector inspector = new AuthenticationMessageInspector(); 
     //clientRuntime.MessageInspectors.Add(inspector); 
    } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
    { 
     AuthenticationMessageInspector inspector = new AuthenticationMessageInspector(); 
     endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector); 
     //Console.WriteLine("Dispatcher Applied!"); 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
    } 

    #endregion 
} 

    public class AuthenticationMessageInspector : IDispatchMessageInspector 

{ 

    #region Members 
    private string conStr = "", commStr = ""; 
    public IDbConnection Connection { get; set; } 
    public IDbCommand Command { get; set; } 
    public IDataReader Reader { get; set; } 

    #endregion   
    private const string HeaderKey = "Authentication"; 
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     //Console.WriteLine("recieved Request! "); 
     int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty); 
     if (headerIndex < 0 || string.IsNullOrEmpty(request.Headers.GetHeader<String>(headerIndex))) 
     { 

      throw (new Exception("Access Denied!\n")); 
      return null; 
     } 


     bool valid = Validate(request.Headers.GetHeader<String>(headerIndex)); 
     if (!valid) 
     { 
      Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex) + " and Access Denied!\n"); 
      throw (new Exception("Access Denied!\n" + request.Headers.GetHeader<String>(headerIndex) + " License Number is not athourized! "));   
     } 
     if (headerIndex != -1) 
     { 
      Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex)); 
     } 
     return null; 

    } 

    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 

    } 
} 

ahora vamos a registrar el comportamiento:

  _routingHost.Description.Endpoints[0].Behaviors.Add(new Gateway.Controllers.AuthenticationBehaviour()); 
_routingHost.Open(); 

que es gracias.

2

Usted está buscando inspector de mensaje. Compruebe esto article.

Editar:

enfoque mencionado es el más fácil en su caso. Creará un inspector de mensajes del cliente para agregar un encabezado personalizado y un inspector de mensajes de despacho para extraer el encabezado y validar la clave. Si la clave no es válida, lanzará una excepción.

La solución limpia es crear custom token y cutom credentials pero es muy complejo por lo menos que desee sumergirse profundamente en los inspectores mensaje Utilizar la aplicación de seguridad de WCF.

+0

Im generando una clave basada en el hardware del cliente y quiero enviar esa clave al servidor con cada solicitud para verificar si la clave es aceptada en el servidor db y luego decidir procesar la solicitud o no – Stacker

+0

Entonces, ¿es una autenticación (simplemente verificando que el cliente con clave pueda acceder al servicio) o autorización (diferentes claves pueden usar diferentes conjuntos de operaciones)? –

+0

simplemente verifique que el cliente con llave pueda acceder al servicio – Stacker

1

he implementado algo como esto para hacer frente a algunas particularmente autenticación "a medida", donde se les permite o niega basado en el estado de base de datos métodos. Utiliza la implementación PerSession, que le permite evitar pasar esa clave cada vez, ya que puede mantener el proxy durante la ejecución. También proporciona algunos beneficios de rendimiento al eliminar la sobrecarga de instanciar el proxy repetidamente (puede no ser un problema según su diseño).

  1. implementar su servicio con un InstanceContextMode de "PerSession" [ServiceBehavior (InstanceContextMode = InstanceContextMode.PerSession)]
  2. proporcionar un método de inicialización en su servicio que acepta la clave, y mantiene una referencia a la misma.
  3. En los métodos de servicio, marque esa clave, otras condiciones, etc., para determinar lo que hay que hacer.
  4. Ahora, cuando usted instancia del proxy de cliente, llame al método de inicialización que pasar primero la tecla, y desde ese punto en adelante se puede proceder a realizar llamadas sin ella.
+0

en realidad lo he implementado ya, muchas gracias por intentar ayudar, utilicé un método diferente, enviaré una respuesta a eso pronto – Stacker

0

Llegué a este artículo cuando intentaba implementar un mecanismo de autenticación en un servicio WCF Rest, intentaba obtener el encabezado de autenticación en el método de inspección de mensajes personalizado AfterReceiveRequest pero tenía problemas para recuperar los encabezados con el System.ServiceModel proporcionado. Canal.objeto de mensaje (solicitud var en la firma del método)

public object AfterReceiveRequest(ref Message request, IClientChannel channel, 
    InstanceContext instanceContext) 
    Dim headerIndex = request.Headers.FindHeader(HeaderKey, String.Empty) 

El headerIndex sería siempre -1, dada esta Me investigado y descubierto que existe un método de extensión a la clase de mensaje que permite convertir el mensaje a un objeto de tipo System.Net.Http.HttpRequestMessage. Para hacerlo, todo lo que se necesita es importar los siguientes conjuntos: System.ServiceModel.Channel, System.Net.Http.

Dim httpReq As System.Net.Http.HttpRequestMessage = request.ToHttpRequestMessage() 

Dim authValue As String 
If httpReq.Headers.Contains(HeaderKey) Then 
    authValue = httpReq.Headers.GetValues(HeaderKey)(0) 
End If 
Cuestiones relacionadas