- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我目前正在为我的一个网站开发一个更好的登录例程,我想解决安全地将登录数据传输到服务器的问题。有几篇关于这个主题的文章和帖子,但他们经常对如何完成有完全不同的看法。
从 SSL 开始,几乎每个人都在同一页上:您应该使用 SSL,我也这样做。然后有人说:“这就足够了,使用 SSL,您可以将用户名和 PW 作为明文发送”。我不同意。其他人说它仍然应该被散列。我读了几篇文章,感觉人们关心登录例程的不同方面,并提出了仅处理其安全方面的机制。
所以我想知道的是,到目前为止我所阐述的例程是否足够,太多还是太少。我将尝试解释为什么我选择实现某个功能以及我尝试涵盖的安全方面:
服务器和客户端之间的通信应该始终是 https://- 尽管如此,我读了几篇文章警告说 SSL 是“没有 Elixir ”,但这是一个好的开始。
许多评论确实拒绝拥有 PW。使用哈希,将其与数据库中经过哈希处理的 PW 进行比较,只需将 PW 从用户输入更改为哈希——攻击者仍然可以通过简单地获取哈希来访问。我同意。但是(这就是我的意思是人们阅读了有关安全性的不同方面)那些声称它比发送明文更好的人,因为在那种情况下只有你的系统,而不是具有相同 PW 的其他系统会受到损害(除非,当然他们还使用哈希 PW)。所以我会在通过 SSL 发送密码之前对密码进行哈希处理。
假设 SSL 无法隐藏我们发送到服务器的数据,并且攻击者会读取经过哈希处理的 PW。我能想到的针对这种情况调整安全性的唯一方法是使用服务器事先发送的 key 加密(例如 AES CBC)客户端 HASHed PW,并且有效期很短. key 必须随机生成。这样,服务器就可以解密数据,然后将HASH与它的数据库进行比较。
总结一下:
-> 客户端希望通过 SSL 登录 -> 服务器发回 key -> PW 的客户端散列 -> 使用 key 和随机 IV 对 HASH 进行客户端加密 -> 服务器使用 key 解密数据(存储在 $_SESSION 中,带有过期时间戳)并将 HASH 与他的数据库中的 HASH 进行比较(如果过期时间戳仍然有效)。
这是个好方法吗?或者这太多了? (安全性会不会太高?)或者您有任何替代解决方案吗?
最佳答案
Or is this too much? (Can there be too much security?)
您所说的安全就像一种液体,必须填满容器而不会溢出。这不是它的工作方式,你问错了问题,这意味着你试图解决错误的问题。这与您堆积的措施数量无关,而是它们是否以及如何解决特定问题。
如果问题是保护传输中的数据,那么解决方案就是 TLS (SSL) - 这就是它专门设计的目的,在最好的情况下,你能想到的任何东西都是一个糟糕的选择给它。您无法超越 TLS 数十年的研究和实践。
虽然 Jay Blanchard 已经回答了这个问题......我想指出你所犯的错误,因为否则它看起来就像一个人的话与另一个人的话(你可能会听,但其他读者可能不会):
- SSL:
The communication between server and client should always be https:// - nevertheless I read several articles warning that SSL is "no silver bullet", but it is a good start.
既是 Elixir 又不是 Elixir ,就看你怎么看了。
当我们谈论保护传输中的数据时,它就是解决方案 - 某种意义上的 Elixir 。
但这并不意味着不会及时发现缺陷,或者您只需打开它并说“我有 TLS,我很安全!” - 不,它仍然需要随着时间的推移进行适当的配置、维护和调整。从这个意义上说,它不是 Elixir 。
它也没有解决许多其他安全问题,所以当有人问“我如何使我的应用程序安全?”时,你当然会说它不是 Elixir ——许多威胁需要单独解决,但没有一个-停止购买它们。
- Hash PW clientside (SHA3, ARGON2i, BCRYPT):
Many comments did reject hasing PW. Using a hash, comparing it to a HASHed PW in the database would simply change the PW from the userinput to the HASH - an attacker would still have access by simply getting hands on the HASH. I agree. BUT (this is what I meant that people read about different aspects of security) the ones claiming that it is better than sending plaintext because in that case ONLY your system, but not other systems with the same PW would be compromised (unless, of course they use also hashed PWs). So I would implement HASHing of the password before sending it via SSL.
恰恰相反 - 当您在客户端对密码进行哈希处理时,这只会使您网站上的帐户在数据泄露后更容易受到损害。
在数据库中查找哈希值 - 密码就在那里,这就是您找出的部分。但是该散列仍然是某个用户提供的字符串的结果……没有什么可以阻止攻击者应用相同的技术来破坏散列以破坏其他服务器上的帐户。
所以,这并不能以任何方式解决问题,但您可能会认为在最坏的情况下它不会做任何坏事......好吧,间接地它会做 - 你必须付出相当大的努力, 去实现一些有很多错误可能性的东西。
在最好的情况下,您只是在浪费时间,但一个小错误可能会成为一个重大漏洞。
此外,SHA-3 是一种加密原语 - 它有许多应用,但主要是作为构建 block 。您不能只将它的一轮放在密码上并对生成的哈希感到满意。
作为比较,bcrypt 在内部使用 Blowfish(作为与 SHA-3 同类的原语),但您不能将 Blowfish 等同于 bcrypt。
- encrypting the HASH:
Let's assume SSL could not hide the data we send to the server and an attacker would read the HASHed PW. The only way that I could think of to adjust the security to this scenario, would be to encrypt (e.g. AES CBC) the client-side HASHed PW with a key that has been send beforehand by the server, and that has a short expiration period. The key would have to be generated randomly. Like that, the server can decrypt the data, and then compare the HASH with the one it its database.
加密密码散列有正当理由,但不是为了这个目的,当然也不是在客户端。
你需要一个安全的 key 交换协议(protocol)才能工作。猜猜你是怎么做到的? TLS。
通过网络传输加密 key 或密码之间几乎没有什么不同。因此,即使这是保护密码的某种解决方案,您将如何在 key 本身上再次应用它?这没有意义。
关于php - 以安全的方式向服务器发送密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48226811/
我一直在阅读有关汇编函数的内容,但对于是使用进入和退出还是仅使用调用/返回指令来快速执行,我感到很困惑。一种方式快而另一种方式更小吗?例如,在不内联函数的情况下,在汇编中执行此操作的最快(stdcal
我正在处理一个元组列表,如下所示: res = [('stori', 'JJ'), ('man', 'NN'), ('unnatur', 'JJ'), ('feel', 'NN'), ('pig',
最近我一直在做很多网络或 IO 绑定(bind)操作,使用线程有助于加快代码速度。我注意到我一直在一遍又一遍地编写这样的代码: threads = [] for machine, user, data
假设我有一个名为 user_stats 的资源,其中包含用户拥有的帖子、评论、喜欢和关注者的数量。是否有一种 RESTful 方式只询问该统计数据的一部分(即,对于 user_stats/3,请告诉我
我有一个简单的 api,它的工作原理是这样的: 用户创建一个请求 ( POST /requests ) 另一个用户检索所有请求 ( GET /requests ) 然后向请求添加报价 ( POST /
考虑以下 CDK Python 中的示例(对于这个问题,不需要 AWS 知识,这应该对基本上任何构建器模式都有效,我只是在这个示例中使用 CDK,因为我使用这个库遇到了这个问题。): from aws
Scala 中管理对象池的首选方法是什么? 我需要单线程创建和删除大规模对象(不需要同步)。在 C++ 中,我使用了静态对象数组。 在 Scala 中处理它的惯用和有效方法是什么? 最佳答案 我会把它
我有一个带有一些内置方法的类。这是该类的抽象示例: class Foo: def __init__(self): self.a = 0 self.b = 0
返回和检查方法执行的 Pythonic 方式 我目前在 python 代码中使用 golang 编码风格,决定移动 pythonic 方式 例子: import sys from typing imp
我正在开发一个 RESTful API。其中一个 URL 允许调用者通过 id 请求特定人员的记录。 返回该 id 不存在的记录的常规值是什么?服务器是否应该发回一个空对象或者一个 404,或者其他什
我正在使用 pathlib.Path() 检查文件是否存在,并使用 rasterio 将其作为图像打开. filename = pathlib.Path("./my_file-name.tif") 但
我正在寻找一种 Pythonic 方式来从列表和字典创建嵌套字典。以下两个语句产生相同的结果: a = [3, 4] b = {'a': 1, 'b': 2} c = dict(zip(b, a))
我有一个正在操裁剪理设备的脚本。设备有时会发生物理故障,当它发生时,我想重置设备并继续执行脚本。我有这个: while True: do_device_control() device
做组合别名的最pythonic和正确的方法是什么? 这是一个假设的场景: class House: def cleanup(self, arg1, arg2, kwarg1=False):
我正在开发一个小型客户端服务器程序来收集订单。我想以“REST(ful)方式”来做到这一点。 我想做的是: 收集所有订单行(产品和数量)并将完整订单发送到服务器 目前我看到有两种选择: 将每个订单行发
我知道在 Groovy 中您可以使用字符串调用类/对象上的方法。例如: Foo."get"(1) /* or */ String meth = "get" Foo."$meth"(1) 有没有办法
在 ECMAScript6 中,您可以使用扩展运算符来解构这样的对象 const {a, ...rest} = obj; 它将 obj 浅拷贝到 rest,不带属性 a。 有没有一种干净的方法可以在
我有几个函数返回数字或None。我希望我的包装函数返回第一个不是 None 的结果。除了下面的方法之外,还有其他方法吗? def func1(): return None def func2(
假设我想设计一个 REST api 来讨论歌曲、专辑和艺术家(实际上我就是这样做的,就像我之前的 1312414 个人一样)。 歌曲资源始终与其所属专辑相关联。相反,专辑资源与其包含的所有歌曲相关联。
这是我认为必须经常出现的问题,但我一直无法找到一个好的解决方案。假设我有一个函数,它可以作为参数传递一个开放资源(如文件或数据库连接对象),或者需要自己创建一个。如果函数需要自己打开文件,最佳实践通常
我是一名优秀的程序员,十分优秀!