套接字验证服务器?

发布于 2024-10-22 01:39:04 字数 2563 浏览 1 评论 0原文

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

我确实意识到我只完成了其中的一小部分,还有很多东西需要学习,但现在在这个阶段我想知道身份验证是如何完成的。

例如,这是服务器代码:

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

如您所见,我确实读取客户端发送的内容并将其输出到控制台,并检查客户端是否发送了退出命令。

  • 我想知道我该怎么做 这样客户端只能连接 如果用户名和密码是 已发送?

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

  • 正确的接收方式是什么 新连接并进行身份验证 拥有它的用户?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

送君千里 2024-10-29 01:39:04

您的想法是正确的,但您需要将其更多地视为状态机。

客户端连接后,需要进入登录状态,您希望它发送身份验证信息。如果不正确或超时,请断开连接。

如果正确,则进入命令处理状态。如果您收到退出命令,请转至清理状态,或直接断开连接。

总体概述如下:

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

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

并且您的 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);
    }
}

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文