我打算开发一个网站,要求用户注册用户名和密码。当我让用户选择密码时,我应该允许用户在密码中包含哪些字符?由于http协议或实现语言的安全问题,有什么我不应该做的吗?
我还没有决定实现语言,但我会使用 Linux。
我打算开发一个网站,要求用户注册用户名和密码。当我让用户选择密码时,我应该允许用户在密码中包含哪些字符?由于http协议或实现语言的安全问题,有什么我不应该做的吗?
我还没有决定实现语言,但我会使用 Linux。
从安全/实现的角度来看,除了 '\0' (无论如何都很难输入)之外,应该没有任何需要禁止字符。您禁止的字符越多,可能密码的总相位空间就越小,因此暴力破解密码的速度就越快。当然,大多数密码猜测实际上使用字典单词而不是输入域的系统搜索......
然而,从可用性的角度来看,某些字符在不同机器上的输入方式并不相同。例如,我在这里有两台不同的计算机,其中 shift-3 在一台上生成 # ,在另一台上生成 £。当我输入密码时,两者都显示为“*”,所以我不知道我是否输入正确。有些人认为这可能会使人们感到困惑,以至于开始禁止这些字符。我认为不值得这样做。大多数真实的人从一台或两台计算机访问真实的服务,并且不倾向于在他们的密码中放置许多扩展字符。
非 ASCII 字符可能存在问题。密码是一个字形序列,但密码处理(散列)将需要一个位序列,因此必须有一种确定性的方法将字形转换为位。这是整个代码页的阴暗沼泽。即使你坚持使用Unicode,也有麻烦:
单个字符可以有多个分解作为代码点。例如,“é”字符(在法语中很常见)可以编码为单个代码点 U+00E9,也可以编码为序列 U+0065 U+0301;这两个序列是等效的。你是否得到一个或另一个取决于输入设备使用的约定。
Unicode 字符串是一个代码点序列(它们是 0 到 1114110 范围内的整数)。有几种标准编码可以将这样的序列转换为字节;最常见的是 UTF-8、UTF-16(大端)、UTF-16(小端)、UTF-32(大端)和 UTF-32(小端)。其中任何一个都可能以 BOM 开头,也可能不以BOM开头。
因此,单个“é”可以有意义地编码为具有至少 20 个不同变体的字节,这就是坚持“主流 Unicode”的时候。Latin-1 编码,或者它的微软对应物,也很普遍,所以把它设为 21。给定的软件将使用哪种编码可能取决于很多因素,包括locale。当用户因为将配置从“加拿大 - 英语”切换到“加拿大 - 法语”而无法再登录他的计算机时,这很麻烦。
实验上,通过将密码限制在可打印的 ASCII 字符范围内(代码范围为 32 到 126 的密码——我个人会避免使用空格,所以将其设为33到 126)并强制执行单字节编码(没有 BOM,一个字符变成一个字节)。由于密码是要在没有视觉反馈的各种键盘上输入的,因此字符列表应该受到更多限制以实现最佳可用性(我每天都在与加拿大的布局作斗争,键盘上写的内容不一定与机器认为的一致是,尤其是在通过一两个嵌套RDP 连接时; '<'、'>' 和 '\' 字符最常移动)。只有字母(大写和小写)和数字,你会没事的。
你可以说用户有责任;他可以自由使用任何他想要的字符,只要他能解决打字问题。但这最终站不住脚:当用户遇到问题时,他们会致电您的帮助台,而您必须承担他们的部分错误。
如果您正在生成随机密码,最好避免使用可能会被其他人混淆的字符。例如(忽略符号):
l, o
I, O
1, 0
除了允许所有字符之外,请考虑在密码字段上设置一个非常大的最大长度,以支持对密码采用密码短语方法的人。
短语“我的密码全部小写”实际上是一个合理的强密码,因为它的长度。