如果在登录屏幕上用户使用其用户名和密码提交表单,则密码将以纯文本形式发送(即使使用POST,如果我错了也请更正) .
那么问题是,保护用户及其密码的正确方法是针对可能窃听通信数据的第三方?
我知道HTTPS是问题的解决方案,但有没有办法确保使用标准HTTP协议(POST请求)至少某种程度的安全性? (也许以某种方式使用javascript)
EDIT 我可能遗漏了一些重要的事情 .
我的目的是一个页面 - 这是PHP生成的登录页面,当然在HTTP GET请求中作为HTML文件发送给用户 . 服务器和客户端之间没有 Build (@Jeremy Powel)连接,所以我无法创建这样的握手协议 . 我希望整个过程对用户透明 - 他想提交密码,而不是处理加密 .
谢谢 .
8 回答
使用HTTP和SSL将使您的生活更轻松,您可以放心,非常聪明的人(至少比我聪明!)多年来仔细检查了这种保密通信方法 .
安全认证是一个广泛的主题 . 简而言之,正如@ jeremy-powell所提到的,总是倾向于通过HTTPS而不是HTTP发送凭据 . 它将带走许多与安全相关的头痛 .
如今,TSL / SSL证书相当便宜 . 事实上,如果您根本不想花钱,那么就有一个免费的 letsencrypt.org - 自动证书颁发机构 .
你可以更进一步,使用 caddyserver.com 在后台调用letsencrypt .
现在,一旦我们将HTTPS取消了......
您不应通过POST有效负载或GET参数发送登录名和密码 . 请改用Authorization标头(基本访问认证方案),其构造如下:
它可能看起来有点复杂,但事实并非如此 . 有很多好的库可以为您提供开箱即用的功能 .
您应该使用Authorization标头有几个很好的理由
这是一个标准
这很简单(在您学习如何使用它们之后)
它允许您在URL级别登录,如下所示:
https://user:password@your.domain.com/login
(Chrome会自动将其转换为Authorization
标头)IMPORTANT:
正如@zaph在下面的评论中指出的那样,将敏感信息作为GET查询发送并不是一个好主意,因为它最有可能最终出现在服务器日志中 .
您可以使用质询响应方案 . 假设客户端和服务器都知道秘密S.然后服务器可以确定客户端知道密码(不给它):
服务器向客户端发送一个随机数R.
客户端将H(R,S)发送回服务器(其中H是加密散列函数,如SHA-256)
Server计算H(R,S)并将其与客户端的响应进行比较 . 如果它们匹配,则服务器知道客户端知道密码 .
Edit:
这里存在一个问题,即R的新鲜度和HTTP无状态这一事实 . 这可以通过让服务器创建一个秘密,称之为Q,只有服务器知道来处理 . 然后协议如下:
服务器生成随机数R.然后发送给客户端H(R,Q)(客户端不能伪造) . 客户端发送R,H(R,Q),并计算H(R,S)并将其全部发送回服务器(其中H是加密散列函数,如SHA-256)服务器计算H(R,S)并将其与客户的回应进行比较 . 然后它需要R并计算(再次)H(R,Q) . 如果客户端的H(R,Q)和H(R,S)版本与服务器的重新计算匹配,则服务器认为客户端已经过身份验证 .
需要注意的是,由于H(R,Q)不能由客户端伪造,因此H(R,Q)充当cookie(因此可以实际上作为cookie实现) .
Another Edit:
之前对协议的编辑是不正确的,因为任何观察过H(R,Q)的人似乎都能够用正确的哈希重放它 . 服务器必须记住哪些R不再新鲜 . 我正在CW这个答案,所以你们可以编辑这个并找出一些好的东西 .
如果您的webhost允许,或者您需要处理敏感数据,请使用HTTPS,period . (法律经常要求afaik) .
否则,如果你想通过HTTP做一些事情 . 我会做这样的事情 .
服务器将其公钥嵌入登录页面 .
客户端填充登录表单并单击“提交” .
AJAX请求从服务器获取当前时间戳 .
客户端脚本连接凭证,时间戳和盐(来自的哈希值)模拟数据,例如 . 鼠标移动,按键事件),使用公钥加密它 .
提交结果哈希 .
服务器解密哈希
检查时间戳是否足够近(仅允许短5-10秒的窗口) . 如果时间戳太旧,则拒绝登录 .
存储哈希值20秒 . 在此间隔期间拒绝用于登录的相同哈希 .
验证用户 .
因此,密码受到保护,无法重播相同的身份验证哈希 .
关于会话令牌的安全性 . 那有点难了 . 但是有可能重新使用被盗的会话令牌 .
服务器设置一个包含随机字符串的额外会话cookie .
浏览器在下一个请求时发回该cookie .
服务器检查cookie中的值,如果它不同则会破坏会话,否则一切都没问题 .
服务器再次使用不同的文本设置cookie .
因此,如果会话令牌被盗,并且其他人发送了请求,那么在原始用户的下一个请求中,会话将被销毁 . 因此,如果用户主动浏览网站,经常点击链接,那么小偷就不会对被盗令牌走得太远 . 可以通过对敏感操作(例如帐户删除)进行另一次认证来强化该方案 .
关于实现:RSA可能是最常见的算法,但对于长密钥来说它很慢 . 我不知道PHP或Javascript实现的速度有多快 . 但可能有更快的算法 .
我会使用服务器端和客户端Diffie-Hellman密钥交换系统与AJAX或多个表单提交(我推荐前者),虽然我没有在互联网上看到任何良好的实现 . 请记住,MITM总是可以破坏或更改JS库 . 在某种程度上,本地存储可用于帮助解决这个问题 .
您可以使用SRP在不安全的通道上使用安全密码 . 优点是,即使攻击者嗅探流量或破坏服务器,他们也无法在不同的服务器上使用密码 . https://github.com/alax/jsrp是一个javascript库,它支持在浏览器或服务器端(通过节点)通过HTTP进行安全密码 .
HTTPS非常强大,因为它使用非对称加密技术 . 这种类型的加密不仅允许您创建加密隧道,还可以验证您是在与正确的人交谈,而不是黑客 .
这是Java源代码,它使用非对称密码RSA(由PGP使用)进行通信:http://www.hushmail.com/services/downloads/
你可以使用ssl为你的主机有ssl的免费项目,如letsencrypt https://letsencrypt.org/