我觉得从移动/网络应用程序到后端api的每个https请求发送用户名和密码是一个坏主意,但我不能提出太多好的论据。
在服务器中,我们……
的 是的 强>
这通常是一个可怕的想法。 WEP是一种旧的网络安全协议,由于其内在的弱点而无法从数据包(信标)获取密码,甚至无需通过网络进行身份验证。这就是为什么我们不在运输中存储这样的凭证。
的 我该怎么做呢? 强>
我建议使用API密钥。这是一个私钥,您可以随程序在数据库中查找并与特定用户关联的每个请求发送该私钥。例如,如果用户(让我们称他为Bob)注册并请求API密钥,您将给他一个密钥(例如 asdf12345 )相当于一张票。只要他每次做某事都会出示他的票,他就可以使用该票执行某些操作。与您在酒店的酒吧/餐厅订购饮料和食物的方式类似,只需出示您的房卡,您每次订购饮品时都需要出示。每次Bob向您的服务器发出请求时,他都需要提供票号 asdf12345 这将允许您看到允许Bob访问这些方法。玛丽没有票,所以当她请求一些数据时,她将被拒绝,因为她没有令牌。
asdf12345
每次用户注册您的网站帐户并请求令牌(并且可能同意您拥有的某些T& Cs)时,您生成GUID /随机哈希并将其存储在 dbo.ApiKeys 表应该包含API密钥和UserId。用户的应用程序应添加此密钥,以便在执行API请求时,他们可以包含此令牌。这可以防止您在每个请求中放弃用户的凭据。这也意味着如果用户设法通过任何方式使他们的API密钥泄露,那通常是他们的错(他们在不安全的连接上使用星巴克,他们将它保存在桌面上的.txt文件中,他们将其写在在他们的桌子上粘滞便笺等)
dbo.ApiKeys
的 编辑:OWASP标准 强>
如果您对进一步阅读感兴趣并希望了解行业标准,OWASP有 一个致力于此的页面 特别的任务。它们是计算机安全最佳实践的通用维基。
这将成为一个很好的安全面试问题,因为它很好地衡量了安全领域的理解水平。
不建议在每个请求中发送用户名/密码,但另一个答案甚至没有触及真正原因。
从技术上讲,用户名/密码是 的 几乎相同的 强> 就像API密钥一样,它们在有效时是等效的。从某种意义上说,API密钥更糟糕,因为根据实现,您通常会将API密钥明文存储在数据库中,而不是正确的散列密码(旁注,但请在散列时使用类似bcrypt或pbkdf2的内容)。你是完全正确的,密码可以像每个请求上的API密钥一样发送,你可以用同样的方式撤销它,等等.API密钥 的 是 强> 密码。在这方面绝对没有区别。
的 然而 强> 在大多数情况下,你仍然可能不会这样做,至少出于以下原因。
的 密码很弱 强> 如果用户选择。如果您有许多用户,许多用户将拥有123456等类似的密码。很容易猜到其中一些。您不需要在API应用程序中运行此风险,但是,在每个请求中发送它或者几乎不会修改此风险,但由于下一个要点,它会稍微改变一下。
的 有时SSL / TLS存在缺陷。 强> 它确实会不时发生针对TLS的新攻击,然后最终修补。但是,有一段时间,攻击者可能从加密流中推断出比特,如果加密内容是部分已知的(即公共密码),这可能会变得更容易。机会不是很高,但问题是,对于许多TLS密码套件,攻击者现在可以记录流量,并在以后解密(因为它需要很长时间,或者该方法尚未发明)。如果他只解密已经过时3年的API密钥,那很好,但是如果它是用户密码......不太好。
的 服务器漏洞 强> 也可能是个问题。不久之前,openssl实现中存在一个漏洞,您可以在其中实际读取部分服务器内存(Web服务器进程)。如果Web服务器一直收到用户密码,它可能会在内存中多次。如果它只是一个临时API密钥(或会话ID或其他),那么攻击者的价值就会降低。它仍然很好,但至少不是密码。
的 内部攻击者 强> 也值得考虑。如果您的服务器上已有攻击者,他可能无法访问数据库以直接读取/修改凭据,但他可能能够在有限的时间内观察Web服务器进程。与上面相同,如果他只能观察临时ID而不是实际密码会好得多。
的 您需要在客户端上存储密码 强> 如果你想随每个请求发送它。在客户端存储敏感内容通常不是一个好主意,为攻击者开辟了可能性。如果用户输入凭据,接收临时令牌并且客户端忘记实际密码通常会更好,直到令牌过期并且用户必须再次提供其密码。从用户体验的角度来看,这当然可能是可接受的 - 但安全性始终是平衡的。 :)
如您所见,在每个请求中发送用户名/密码不是直接漏洞。事实上,在许多场景中它甚至可以被接受。但是你可以通过使用临时凭证使其更安全,如果成本合理,为什么不呢?