0

我有几个关于客户端服务器模型的问题。我当前的应用程序(或者更确切地说是我提议的应用程序)使用中央服务器,不同的客户端可以连接到它。

(对于想要回答问题但不知道的人的 O(n) 的小解释,无论是谷歌还是按照这个例子:

考虑一个包含 n 个元素的列表。O(1) 意味着您可以只选择元素,而 O(n) 基本上意味着您可能必须遍历每个元素(因此 n 个元素)才能获得所需的项目。O(log n) 是一种与递归细分有关的中间方法,它仍然比 O(n) 快很多,但没有 O(1) 快。)

问题一:

我如何有效地检索用户记录,我不知道服务器在某个时候必须处理多少用户,但我坚信如果 O(1) 可以合理实施,O(n) 操作是不够的。

第一部分是关于登录过程,我打算让用户使用个人标识符(用户名/电子邮件/等)和密码登录,一旦有人尝试登录,此信息就会发送到服务器。

此外,我还计划不直接使用数据库(例如 MySQL),而纯粹出于“备份”目的(如果可能,服务器应将所有信息存储在 RAM 中,并且仅将其写入数据库,以便在通电时不会丢失任何信息丢失的)。

所以基本上服务器需要存储客户端数据(包括个人标识符,还有一个唯一的ID)。

我目前的想法:

  1. 存储在列表中,但是搜索用户(然后验证他的信息)可能需要 O(n) 时间,具体取决于排序,如果我对用户名进行字母排序,我可以将其减少到 O(log n) .

  2. 第二个建议是将其存储在 Client[] 数组中,并将 UniqueID 作为键。然后在 O(1) 中访问应该是可能的,这是理想的,但是我使用这种方法遇到的问题是如何将用户放入并发送到服务器的个人标识符(用户名等)转换为他的唯一身份?如果我使用 List 之类的东西,那么时间将再次变为 O(n)。此外,数组大小可能不会不成比例地巨大,因为它只会分配太多内存,例如,我不认为散列用户名是理想的,我也不确定它是否会创建一个唯一的 ID。

问题2:

其次,我当然也希望我的用户数据是安全的。现在假设底层 MySQL 服务器(数据在启动时从它加载到服务器的 RAM 中)是安全的。

然后我想知道在这些条件下保存的密码(当然是加密的)是否也安全?

  1. 没有任何东西可以直接物理访问服务器。

  2. 通信协议没有检索密码信息的命令或包含密码信息的超集,这意味着服务器在任何情况下都不会给出密码。

  3. 密码作为私有变量存储在服务器 RAM 中的客户端对象中。

  4. 要检查用户输入的信息是否正确,Client 对象具有类似client.confirmPassword(password).

因此,除非我忘记了事情,否则问题基本上归结为服务器的 RAM 是否可以直接读取,因为它仅通过通信协议连接到外部世界?

帖子结果很长,但我希望周围有人可以回答这些问题:)

4

4 回答 4

1

你担心错误的原因

  1. 您需要了解的一件事是,数据库系统是一个复杂的系统。搜索查询非常复杂,性能非常高,您不必害怕在需要的地方使用它。数据库系统实际上将活动数据库的所有信息都存储到内存中......并且它们被缓存,然后仅在服务关闭后才写入硬盘驱动器:这就是您要重做的事情。
  2. MD5 和 SHA1 是强大的哈希值,可以代替密码直接存储。您可以在大多数编程语言中找到对这些的调用。现在您可以将这些哈希存储在数据库中,然后对哈希进行比较,这是非常安全的。

做已经构建好的解决方案(如数据库、库等)要容易得多。它们是为性能而设计的,并且对错误输入非常免疫,也有更好的方法来处理最坏的情况。

于 2013-05-03T17:02:39.520 回答
1

问题1)

我会考虑使用哈希图。它可以访问 O(1)。你甚至可以使用多个哈希图:

  • 映射 userById
  • 映射用户名

由于并发,您应该查看不同的地图实现。

问题2)

只要密码被正确加密,我认为你很好。在常规情况下,服务器内存被认为是安全的。

您可能对这个其他问题感兴趣: Best way to store password in database

于 2013-05-03T17:11:31.780 回答
1
  1. 简单的答案就是使用数据库,因为其他人已经花时间让它快速并为您优化。您可以查看 mysql 功能,例如缓存和内存表,这将有助于提高性能。但是如果你真的不想使用数据库,那么你应该对用户名进行哈希处理。如果您的用户名必须是唯一的,那么好的散列将始终提供唯一的 id。如果您有兴趣探索其他选项,还可以查看 TreeMaps 之类的东西。
  2. 这真的取决于你最关心的是什么。一个优秀的黑客可以做各种你意想不到的事情。您最好的防御措施是确保卸载服务器上运行的任何您不需要的东西,并关闭您不使用的任何端口。
于 2013-05-03T17:15:13.163 回答
1

与答案 tkr 的答案相反,Hashmap 没有 O(1) 性能。请看这个问题:“Java hasmap 真的是 O(1)”

根据服务器的多线程性质和您希望进行同步的方式,您仍然可以使用Hashmapor Hashtable,但请记住,性能介于 O(1) 和 O(n) 之间,具体取决于哈希冲突。还要记住,哈希函数本身会导致开销。或者,您可能想查看二叉树 (O(log(n))

我的选择仍然是使用数据库;正如其他人所说,数据库将经常访问的数据存储到内存中,因此非常适合此类任务。您可以运行本地内存数据库(例如 HSQLDB)并在关闭时将数据刷新到外部服务器,并在启动时从那里加载。

至于将密码存储在数据库中,请确保使用安全的散列函数,例如 SHA-1。如果有人意外访问您的密码数据库,请不要忘记对密码进行加盐,以使密码解密更加困难。

于 2013-05-03T21:11:46.370 回答