1) 我有一个 std::map,其中键是客户端 IP,值是帐户 ID。身份验证后,服务器将客户端的 ip 和它的帐户 ID 存储到此映射中,然后当服务器收到客户端的请求时,它会检查它的 ip 并在映射中查找它。
IP 本身是不够的:可能有多个不同的客户端从同一个 IP 连接(来自同一台计算机,或者来自 NAT 后面的不同计算机,因此您只能看到 NAT IP)。如果想要基于 IP 的唯一密钥,则需要使用客户端的 IP/端口元组。
2) 我有一个 std::map,其中键是随机生成的键,值是帐户 ID。认证后,服务器为这个特定的客户端生成随机密钥,将此密钥发送给客户端,客户端保存以供进一步使用,服务器将此密钥和帐户ID存储在地图中。
这是非常危险的:是什么禁止客户端发送另一个客户端的“会话 id”而不是他的,从而劫持另一个客户端的会话?这与您可能想要阅读的 HTTP Session Hijacking 完全相同。简而言之:如果可以避免,就不要这样做。
其他可能的解决方案:
很遗憾,只要我们不知道您的服务器使用的模型(线程、分叉、选择、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, 0));
if (sock_client >= 0)
new ClientSession(sock_client);
警告:显然这段代码有缺陷,它从不破坏 ClientSession 对象,所以它有内存泄漏,但我的意思是展示如何将线程与特定的session 对象,我将根据您的具体架构和需求,让您管理对象的生命周期。