Click or drag to resize
AuthenticatedMessagingFactory Class
Extension for authentication during connecting.
Inheritance Hierarchy
SystemObject
  Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnectionAuthenticatedMessagingFactory

Namespace: Eneter.Messaging.MessagingSystems.Composites.AuthenticatedConnection
Assembly: Eneter.Messaging.Framework (in Eneter.Messaging.Framework.dll) Version: 7.0.0.0 (7.0.0.0)
Syntax
public class AuthenticatedMessagingFactory : IMessagingSystemFactory

The AuthenticatedMessagingFactory type exposes the following members.

Constructors
Methods
  NameDescription
Public methodCreateDuplexInputChannel
Creates duplex input channel which performs the authentication procedure.
Public methodCreateDuplexOutputChannel(String)
Creates duplex output channel which performs authentication procedure during opening the connection.
Public methodCreateDuplexOutputChannel(String, String)
Creates duplex output channel which performs authentication procedure during opening the connection.
Public methodEquals
Determines whether the specified Object is equal to the current Object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetHashCode
Serves as a hash function for a particular type.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Top
Properties
  NameDescription
Public propertyAuthenticationTimeout
Gets/sets maximum time until the authentication procedure must be performed.
Public propertyOutputChannelThreading
Gets or sets the threading mode for the authenticated output channel.
Top
Remarks
Here is how the authentication procedure works:
  1. AuthenticatedDuplexOutputChannel calls getLoginMessage callback and gets the login message. Then sends it to AuthenticatedDuplexInputChannel.
  2. AuthenticatedDuplexInputChannel receives the login message and calls getHandshakeMessage callback. The returned handshake message is sent to AuthenticatedDuplexOutputChannel.
  3. AuthenticatedDuplexOutputChannel receives the handshake message and calls getHandshakeResponseMessage. The returned handshake response message is then sent to AuthenticatedDuplexInputChannel.
  4. AuthenticatedDuplexInputChannel receives the handshake response message and calls authenticate callback. if it returns true the connection is established.
Examples
Service side using the authentication:
class Program
{
    private static Dictionary<string, string> myUsers = new Dictionary<string, string>();
    private static IDuplexStringMessageReceiver myReceiver;

    static void Main(string[] args)
    {
        //EneterTrace.TraceLog = new StreamWriter("d:/tracefile.txt");

        // Simulate users.
        myUsers["John"] = "password1";
        myUsers["Steve"] = "password2";

        // Create TCP based messaging.
        IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();

        // Connecting clients will be authenticated.
        IMessagingSystemFactory aMessaging = new AuthenticatedMessagingFactory(aTcpMessaging, GetHandshakeMessage, Authenticate);
        IDuplexInputChannel anInputChannel = aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8092/");

        // Use text messages.
        IDuplexStringMessagesFactory aStringMessagesFactory = new DuplexStringMessagesFactory();
        myReceiver = aStringMessagesFactory.CreateDuplexStringMessageReceiver();
        myReceiver.RequestReceived += OnRequestReceived;

        // Attach input channel and start listening.
        // Note: using AuthenticatedMessaging will ensure the connection will be established only
        //       if the authentication procedure passes.
        myReceiver.AttachDuplexInputChannel(anInputChannel);

        Console.WriteLine("Service is running. Press Enter to stop.");
        Console.ReadLine();

        // Detach input channel and stop listening.
        // Note: tis will release the listening thread.
        myReceiver.DetachDuplexInputChannel();
    }

    private static void OnRequestReceived(object sender, StringRequestReceivedEventArgs e)
    {
        // Handle received messages here.
        Console.WriteLine(e.RequestMessage);

        // Send back the response.
        myReceiver.SendResponseMessage(e.ResponseReceiverId, "Hello");
    }

    private static object GetHandshakeMessage(string channelId, string responseReceiverId, object loginMessage)
    {
        // Check if login is ok.
        if (loginMessage is string)
        {
            string aLoginName = (string)loginMessage;
            if (myUsers.ContainsKey(aLoginName))
            {
                // Login is OK so generate the handshake message.
                // e.g. generate GUI.
                return Guid.NewGuid().ToString();
            }
        }

        // Login was not ok so there is not handshake message
        // and the connection will be closed.
        EneterTrace.Warning("Login was not ok. The connection will be closed.");
        return null;
    }

    private static bool Authenticate(string channelId, string responseReceiverId, object loginMessage,
        object handshakeMessage, object handshakeResponseMessage)
    {
        if (loginMessage is string)
        {
            // Get the password associated with the user.
            string aLoginName = (string) loginMessage;
            string aPassword;
            myUsers.TryGetValue(aLoginName, out aPassword);

            // E.g. handshake response may be encrypted original handshake message.
            //      So decrypt incoming handshake response and check if it is equal to original handshake message.
            try
            {
                ISerializer aSerializer = new AesSerializer(aPassword);
                string aDecodedHandshakeResponse = aSerializer.Deserialize<string>(handshakeResponseMessage);
                string anOriginalHandshake = (string) handshakeMessage;
                if (anOriginalHandshake == aDecodedHandshakeResponse)
                {
                    // The handshake response is correct so the connection can be established.
                    return true;
                }
            }
            catch (Exception err)
            {
                // Decoding of the response message failed.
                // The authentication will not pass.
                EneterTrace.Warning("Decoding handshake message failed.", err);
            }
        }

        // Authentication did not pass.
        EneterTrace.Warning("Authentication did not pass. The connection will be closed.");
        return false;
    }
}
Examples
Client using the authentication:
class Program
{
    private static IDuplexStringMessageSender mySender;

    static void Main(string[] args)
    {
        // TCP messaging.
        IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();

        // Authenticated messaging uses TCP as the underlying messaging.
        IMessagingSystemFactory aMessaging = new AuthenticatedMessagingFactory(aTcpMessaging, GetLoginMessage, GetHandshakeResponseMessage);
        IDuplexOutputChannel anOutputChannel = aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:8092/");

        // Use text messages.
        mySender = new DuplexStringMessagesFactory().CreateDuplexStringMessageSender();

        // Subscribe to receive response messages.
        mySender.ResponseReceived += OnResponseMessageReceived;

        // Attach output channel and connect the service.
        mySender.AttachDuplexOutputChannel(anOutputChannel);

        // Send a message.
        mySender.SendMessage("Hello");

        Console.WriteLine("Client sent the message. Press ENTER to stop.");
        Console.ReadLine();

        // Detach output channel and stop listening.
        // Note: it releases the tread listening to responses.
        mySender.DetachDuplexOutputChannel();
    }

    private static void OnResponseMessageReceived(object sender, StringResponseReceivedEventArgs e)
    {
        // Process the incoming response here.
        Console.WriteLine(e.ResponseMessage);
    }

    public static object GetLoginMessage(string channelId, string responseReceiverId)
    {
        return "John";
    }

    public static object GetHandshakeResponseMessage(string channelId, string responseReceiverId, object handshakeMessage)
    {
        try
        {
            // Handshake response is encoded handshake message.
            ISerializer aSerializer = new AesSerializer("password1");
            object aHandshakeResponse = aSerializer.Serialize<string>((string)handshakeMessage);

            return aHandshakeResponse;
        }
        catch (Exception err)
        {
            EneterTrace.Warning("Processing handshake message failed. The connection will be closed.", err);
        }

        return null;
    }
}
Version Information

.NET

Supported in: .NET 4.5, .NET 4.0, .NET 3.5

Compact Framework

Supported in: Compact Framework 3.5, Compact Framework 2.0

Mono

Supported in: Mono 2.6.4

Silverlight

Supported in: Silverlight 5, Silverlight 4, Silverlight 3

Windows Phone

Supported in: Windows Phone 8.1, Windows Phone 8.0, Windows Phone 7.1, Windows Phone 7
See Also