加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在服务器端识别客户端的方法

发布时间:2020-12-16 09:44:10 所属栏目:百科 来源:网络整理
导读:我正在用C创建客户端 – 服务器应用程序.服务器将接受来自多个客户端的请求每个客户在服务器上创建个人帐户.身份验证后,我知道客户端使用特定的ip登录到特定帐户.现在我想确定哪些请求考虑特定帐户,例如: 客户A登录: username: userpassword: pass123 服务
我正在用C创建客户端 – 服务器应用程序.服务器将接受来自多个客户端的请求每个客户在服务器上创建个人帐户.身份验证后,我知道客户端使用特定的ip登录到特定帐户.现在我想确定哪些请求考虑特定帐户,例如:

客户A登录:

username: user
password: pass123

服务器发现这些数据与id = 3的帐户匹配.

现在当这个客户端A发送一些请求时,我希望服务器访问(并最终改变)id = 3的帐户.到目前为止,我已经提出了这两个想法:

>我有一个std :: map,其中key是客户端ip,值是帐户ID.在身份验证之后,服务器将客户端的ip及其帐户ID存储到此映射中,稍后当服务器收到来自客户端的请求时,它会检查它的ip并在映射中查找它.
>我有一个std :: map,其中key是随机生成的key,value是account id.验证后,服务器为此特定客户端生成随机密钥,将此密钥发送给客户端,客户端将其保存以供进一步使用,服务器将此密钥和帐户ID存储在映射中.

我想知道这些是否是处理这类问题的好方法.哪一个更好,还考虑安全性(这对我来说非常重要)?还是有更好的方法?

解决方法

1) I have a std::map where key is client ip and value is account id. After authentication,server stores client’s ip and it’s account id into this map and later when server receives request from client,it checks it’s ip and looks for it in map.

IP本身是不够的:可以有几个不同的客户端连接来自同一个IP(来自同一台计算机,或来自NAT后面的不同计算机,因此您只能看到NAT IP).如果您需要基于IP的唯一密钥,则需要使用客户端的IP /端口元组.

2) I have a std::map where key is randomly generated key and value is account id. After authentication,server generates random key for this specific client,sends this key to client,client saves it for further use,server stores this key and account id in map.

这是非常危险的:什么禁止客户端发送另一个客户端的“会话ID”而不是他的一个,从而劫持了另一个客户端的会话?这与您可能想要阅读的HTTP会话劫持问题完全相同.简而言之:如果你能避免它,就不要这样做.

其他可能的方案:

>仍然使用std :: map,您可以使用套接字句柄作为密钥:它在服务器上必然是唯一的,因此不会产生混淆,并且它使您无需在每条消息中检索客户端的IP /端口.
>如果您的服务器使用旧的“每个连接一个线程”模型,那么您不必跳过这些环节.只需将会话数据与线程本地存储变量相关联即可.或者,几乎所有线程库都允许您将参数传递给线程,这可用于将特定数据与您的线程相关联(请参阅下面的示例).
>如果您的服务器使用旧的“每个连接一个进程”模型(fork),那么它就更容易了,每个进程都有自己的变量,因此您没有任何特殊操作.

不幸的是,只要我们不知道你的服务器使用的模型(线程,分叉,选择,aio,……?),你的问题就是开放式的,所以你很难给出明确的答案.

如果您使用的是线程模型,这里(大致)我通常如何做(C 11线程,但任何其他线程库也可以这样做):

class ClientSession {
public:
    ClientSession(int sock)
        : m_sock(sock),m_thread(&ClientSession::threadFunction,this)
    {
    }
private:
    int m_sock;
    WhateverType m_someSessionVariable;

    std::thread m_thread; // the thread object should be declared last so that
    // it is initialised last in the constructor,thus avoiding race conditions
    // during the initialisation (you really don't want the thread to access
    // your member variables if they are not yet initialised!)

    static void threadFunction(ClientSession* object) {
      object->threadMethod();
    }

    void threadMethod() {
      // handle your connection
      // the current ClientSession object (this) *is* your session
      // put whatever you want in it,eg. m_someSessionVariable
    }
};

//...

int sock_client = TEMP_FAILURE_RETRY(accept(sock_server,0));
if (sock_client >= 0)
  new ClientSession(sock_client);

警告:显然这段代码有缺陷,它永远不会破坏ClientSession对象,因此它有内存泄漏但我的目的是展示如何将一个线程与一个特定的会话对象相关联,我将留给你管理对象的生命周期取决于您的确切架构和需求.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读