java 套接字认证服务器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5321003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:37:59  来源:igfitidea点击:

Socket Authentication Server?

javaauthenticationclientcommunication

提问by Guapo

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.

我目前正在使用 java 为桌面应用程序创建身份验证服务器,到目前为止,我已经能够让客户端和服务器像聊天服务器/客户端一样开始通信。

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 ?

  • 我想知道的是,如果发送了用户和密码,我将如何做才能使客户端只能连接到它?

  • 或者我应该总是接收初始连接并从那里接收身份验证信息,如果客户端没有在假设 3 秒内发送它,请断开它们?

  • 接收新连接并使用它验证用户的正确方法是什么?

回答by Jonathan

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 processLoginfunction could look like this:

您的processLogin函数可能如下所示:

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 processCommandfunction:

还有你的processCommand功能:

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 stateinstance 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.

state实例变量很可能是一个枚举。您可以看到使用此模型将为您提供一些非常简单的可扩展性。例如,一个命令可以让你进入一个不同的状态来处理特定的子命令。