我正在创建一个使用 HTTPS 的基于 Web 的安全 API;但是,如果我允许用户使用查询字符串来配置它(包括发送密码),这也是安全的还是我应该强制它通过 POST 完成?
是的。但是出于以下几个原因,对敏感数据使用 GET 是一个坏主意:
主要是 HTTP referrer 泄漏(目标页面中的外部图像可能会泄漏密码 [1])
密码将存储在服务器日志中(这显然很糟糕)
浏览器中的历史缓存
因此,即使查询字符串是安全的,也不建议通过查询字符串传输敏感数据。
[1] 虽然我需要注意 RFC 声明浏览器不应将引用者从 HTTPS 发送到 HTTP。但这并不意味着糟糕的第 3 方浏览器工具栏或来自 HTTPS 站点的外部图像/闪存不会泄露它。
从“嗅探网络数据包”的角度来看,GET 请求是安全的,因为浏览器将首先建立安全连接,然后发送包含 GET 参数的请求。但是 GET url 将存储在用户浏览器历史记录/自动完成中,这不是存储例如密码数据的好地方。当然,这仅适用于可能从浏览器访问服务的更广泛的“Webservice”定义,如果您仅从您的自定义应用程序访问它,这应该不是问题。
因此,至少应该首选将 post 用于密码对话框。同样正如链接 littlegeek 所指出的那样,GET URL 更有可能被写入您的服务器日志。
是的,您的查询字符串将被加密。
背后的原因是查询字符串是 HTTP 协议的一部分,它是一个应用层协议,而安全性(SSL/TLS)部分来自传输层。首先建立 SSL 连接,然后将查询参数(属于 HTTP 协议)发送到服务器。
建立 SSL 连接时,您的客户端将按顺序执行以下步骤。假设您尝试登录名为 example.com 的站点并希望使用查询参数发送您的凭据。您的完整 URL 可能如下所示:
https://example.com/login?username=alice&password=12345)
您的客户端(例如,浏览器/移动应用程序)将首先使用 DNS 请求将您的域名 example.com 解析为 IP 地址 (124.21.12.31)。查询该信息时,仅使用域特定信息,即仅使用 example.com。现在,您的客户端将尝试使用 IP 地址 124.21.12.31 连接到服务器,并将尝试连接到端口 443(SSL 服务端口不是默认的 HTTP 端口 80)。现在,example.com 上的服务器会将其证书发送给您的客户端。您的客户端将验证证书并开始为您的会话交换共享密钥。成功建立安全连接后,您的查询参数才会通过安全连接发送。
因此,您不会暴露敏感数据。但是,使用此方法通过 HTTPS 会话发送您的凭据并不是最好的方法。你应该采取不同的方法。
(e.g http://example.com/login?username=alice&password=12345)
相冲突。
是的。 HTTPS 会话的整个文本由 SSL 保护。这包括查询和标题。在这方面,POST 和 GET 将完全相同。
至于您的方法的安全性,如果没有适当的检查,就没有真正的说法。
SSL 首先连接到主机,因此主机名和端口号以明文形式传输。当主机响应并且挑战成功时,客户端将使用实际 URL(即第三个斜线之后的任何内容)加密 HTTP 请求并将其发送到服务器。
有几种方法可以破坏这种安全性。
可以将代理配置为充当“中间人”。基本上,浏览器将连接到真实服务器的请求发送到代理。如果以这种方式配置代理,它将通过 SSL 连接到真实服务器,但浏览器仍将与代理通信。因此,如果攻击者可以访问代理,他可以以明文形式查看流经它的所有数据。
您的请求也将在浏览器历史记录中可见。用户可能会想为该站点添加书签。一些用户安装了书签同步工具,因此密码可能会出现在 deli.ci.us 或其他地方。
最后,可能有人入侵了您的计算机并安装了键盘记录器或屏幕抓取工具(许多特洛伊木马类型的病毒都会这样做)。由于密码直接在屏幕上可见(与密码对话框中的“*”相反),这是另一个安全漏洞。
结论:在安全性方面,始终依靠人迹罕至的道路。有太多你不知道,不会想到的事情,这会伤到你的脖子。
是的,只要没有人在你的肩膀上看着显示器。
我不同意 Slough's response 中关于[...] HTTP 引荐来源网址泄露(目标页面中的外部图像可能泄露密码) 的说法。
HTTP 1.1 RFC explicitly states:
如果引用页面是使用安全协议传输的,则客户端不应在(非安全)HTTP 请求中包含Referer 头字段。
无论如何,服务器日志和浏览器历史是不将敏感数据放入查询字符串的充分理由。
是的,从您建立 HTTPS 连接的那一刻起,一切都是安全的。作为 POST 的查询字符串 (GET) 通过 SSL 发送。
您可以将密码作为 MD5 哈希参数发送,并添加一些盐。在服务器端进行比较以进行身份验证。