Socket Authentication Server?

19,170

You've got the right idea, but you need to think of it more as a state machine.

A client connects, then it would need to go into the Login state, where you expect it to send authentication information. If incorrect or timeout, disconnect.

If correct, move on to the Command Processing state. If you receive a quit command, either move to a Cleanup state, or simply disconnect.

Here's a general outline:

String line;
while ((line = in.readLine()) != null) {
    switch (state) {
        case login:
            processLogin(line);
            break;
        case command:
            processCommand(line);
            break;
    }
}

Your processLogin function could look like this:

void processLogin(String line) {
    if (user == null) {
        user = line;
    }
    else if (password == null) {
        password = line;
    }
    else {
        if (validUser(user, password)) {
            state = command;
        }
        else {
            socket.close();
        }
    }
}

And your processCommand function:

void processCommand(String line) {
    if (line.equals(...)) {
        // Process each command like this
    }
    else if (line.equals("quit")) {
        socket.close();
    }
    else {
        System.err.println("Unrecognized command: " + line);
    }
}

The state instance variable would likely be an enum. You can see that using this model will give you some pretty simple extensibility. For example, a command could drop you into a different state to process specific sub-commands.

Share:
19,170
Guapo
Author by

Guapo

Updated on July 09, 2022

Comments

  • Guapo
    Guapo almost 2 years

    I am currently playing with java to create an authentication server for a desktop app and so far I have been able to make both the client and server communicate like a chat server/client for a start.

    I do realise I only got a small portion of it working and there are many things to come and to learn but right now at this stage I am wondering how the authentication is done.

    For example, this is the server code:

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class LoginServer
    {
        public static void main(String[] args) throws Exception {
            int port = 7000;
            int id = 1;
    
            ServerSocket loginserver = null;
            try
            {
                loginserver = new ServerSocket(port);
                System.out.println("LoginServer started...");
            }
            catch (IOException e) {
                System.out.println("Could not listen on port: " + port);
                System.exit(-1);
            }
    
            while (true)
            {
                Socket clientSocket = loginserver.accept();
                ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
                cliThread.start();
            }
        }
    }
    
    class ClientServiceThread extends Thread
    {
        Socket clientSocket;
        int clientID = -1;
        boolean running = true;
    
        ClientServiceThread(Socket s, int i)
        {
            clientSocket = s;
            clientID = i;
        }
    
        public void run()
        {
            System.out.println("Accepted Client : ID - " + clientID + " : Address - " + clientSocket.getInetAddress().getHostName());
            try
            {
                BufferedReader   in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter   out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
                while (running)
                {
                    String clientCommand = in.readLine();
                    System.out.println("Client Says :" + clientCommand);
                    if (clientCommand.equalsIgnoreCase("quit"))
                    {
                        running = false;
                        System.out.print("Stopping client thread for client : " + clientID);
                    }
                    else
                    {
                        out.println(clientCommand);
                        out.flush();
                    }
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    

    As you can see, I do read what the client sends and output it to the console as well as checking if the client has sent a quit or not command.

    • What I am wondering is how would I do so that the client can only connect to it if the user and password was sent ?

    • Or should I always receive the initial connection and from there receive the authentication information and if the client has not sent it in let's say 3 seconds disconnect them ?

    • What is the correct way of receiving the new connections and authenticate the users with it ?