PHP 开发人员需要了解 https/安全套接字层连接的哪些信息?
题
对于 https 连接的方式和原因,我几乎一无所知。显然,当我传输密码等安全数据或特别是信用卡信息时,https 是一个关键工具。不过,我需要了解什么?您看到开发人员在项目中实施它时最常见的错误是什么?有时 https 是个坏主意?谢谢!
解决方案
HTTPS 或安全套接字层 (SSL) 证书为站点提供服务,通常由证书颁发机构 (CA) 签名,该证书颁发机构实际上是受信任的第三方,用于验证有关站点的一些基本详细信息,并验证其使用在浏览器中。如果您的浏览器信任 CA,那么它就会信任该 CA 签名的任何证书(这称为信任链)。
每个 HTTP(或 HTTPS)请求由两部分组成:一个请求,一个响应。当您通过 HTTPS 请求某些内容时,实际上后台会发生一些事情:
- 客户端(浏览器)进行“握手”,请求服务器的公钥和标识。
- 此时,浏览器可以检查有效性(站点名称是否匹配?该日期范围是当前的吗?它是由它信任的 CA 签署的吗?)。它甚至可以联系 CA 并确保证书有效。
- 客户端创建一个新的预主密钥,该密钥使用服务器的公钥加密(因此只有服务器可以解密)并发送给服务器
- 服务器和客户端都使用此预主密钥来生成主密钥,然后使用该主密钥为实际数据交换创建对称会话密钥
- 双方发送消息表示握手已完成
- 然后服务器正常处理请求,然后使用会话密钥加密响应
如果连接保持打开状态,则每个连接将使用相同的对称密钥。
如果建立了新的连接,并且双方仍然拥有主密钥,则可以在“简短握手”中生成新的会话密钥。通常,浏览器会存储主密钥直到其关闭,而服务器会将其存储几分钟或几个小时(取决于配置)。
有关会话时长的更多信息,请参阅 HTTPS 对称密钥的有效期是多长时间?
证书和主机名
证书被分配一个通用名称 (CN),对于 HTTPS 来说是域名。CN 必须完全匹配,例如,CN 为“example.com”的证书将与域“www.example.com”不匹配,用户将在浏览器中收到警告。
前 神经网络研究所, ,不可能在一个 IP 上托管多个域名。因为证书是在客户端发送实际的 HTTP 请求之前获取的,并且 HTTP 请求包含 Host:标头行告诉服务器要使用什么 URL,服务器无法知道为给定请求提供什么证书。SNI 将主机名添加到 TLS 握手的一部分,因此只要客户端和服务器都支持它(并且在 2015 年,它得到了广泛支持),那么服务器就可以选择正确的证书。
即使没有 SNI,提供多个主机名的一种方法是使用包含主题备用名称 (SAN) 的证书,这些证书本质上是证书有效的附加域。例如,谷歌使用单一证书来保护其许多网站的安全。
另一种方法是使用通配符证书。可以获得类似“.example.com”,在这种情况下,“www.example.com”和“foo.example.com”都对该证书有效。但是,请注意“example.com”与“.example.com”,“foo.bar.example.com”也没有。如果您将“ www.example.com”用于证书,则应将“ example.com”中的任何人重定向到“ www”。地点。如果他们要求 https://example.com, ,除非您将其托管在单独的 IP 上并且拥有两个证书,否则将会出现证书错误。
当然,您可以混合使用通配符和 SAN(只要您的 CA 允许您这样做)并获得“example.com”和 SAN 的证书“.example.com”、“example.net”和“.example.net”,例如。
形式
严格来说,如果您提交表单,表单页面本身是否未加密并不重要,只要提交 URL 转到 https:// URL 即可。实际上,用户已经接受过培训(至少在理论上),除非看到小“锁定图标”,否则不要提交页面,因此即使是表单本身也应该通过 HTTPS 来获取此信息。
流量和服务器负载
HTTPS 流量比同等的 HTTP 流量大得多(由于加密和证书开销),并且它也给服务器带来了更大的压力(加密和解密)。如果您的服务器负载很重,那么可能需要对使用 HTTPS 提供的内容进行严格筛选。
最佳实践
如果您不只是在整个网站上使用 HTTPS,它应该根据需要自动重定向到 HTTPS。每当用户登录时,他们应该使用 HTTPS,如果您使用会话 cookie,则 cookie 应该具有 安全标志设置. 。这可以防止会话 cookie 被拦截,考虑到开放(未加密)wifi 网络的流行,这一点尤其重要。
页面上的任何资源都应该来自该页面使用的相同方案。如果您在使用 HTTPS 加载页面时尝试从 http:// 获取图像,用户将收到安全警告。您应该使用完全限定的 URL,或者另一种简单的方法是使用不包含主机名的绝对 URL(例如,src="/images/foo.png"),因为它们对两者都适用。
- 这包括外部资源(例如 Google Analytics)
从 HTTPS 更改为 HTTP 时,不要执行 POST(表单提交)。大多数浏览器会将其标记为安全警告。
其他提示
一般来说,我不会深入讨论 SSL,gregmac 在这方面做得很好,请参见下文;-)。
然而,在使用 SSL/TLS 方面,一些最常见(也是关键)的错误(不是特定的 PHP):
- 当您应该强制执行 HTTPS 时却允许 HTTP
- 通过 HTTP 从 HTTPS 页面检索一些资源(例如图像、IFRAME 等)
无意中从 HTTPS 页面定向到 HTTP 页面 - 请注意,这包括“假”页面,例如“about:blank”(我见过它用作 IFRAME 占位符),这将不必要且令人不快地弹出警告。
配置为支持旧的、不安全版本的 SSL 的 Web 服务器(例如SSL V2很常见,但可怕)(好吧,这不是程序员的问题,但有时没有人会处理它...)
配置为支持不安全的密码套件的Web服务器(我只看到使用Null Cipher,这基本上提供了绝对没有加密)(同上)
自签名证书 - 防止用户验证站点的身份。
从 HTTP 页面请求用户的凭据,即使提交到 HTTPS 页面也是如此。同样,这会阻止用户在提供密码之前验证服务器的身份......即使密码以加密方式传输,用户也无法知道他是否在伪造的网站上 - 或者即使密码是否会被加密。
Non-secure cookie - 与安全相关的cookie(例如sessionId、身份验证令牌、访问令牌等) 必须 被设置为“安全”属性集。这个很重要!如果未设置为安全,则安全 cookie,例如SessionId,可以通过 HTTP 传输(!) - 攻击者可以确保这种情况发生 - 从而允许会话劫持等。当您这样做时(尽管这没有直接相关),也请在您的 cookie 上设置 HttpOnly 属性(有助于减轻一些 XSS)。
过于宽松的证书 - 假设您有多个子域,但并非所有子域都处于相同的信任级别。例如,您有 www.yourdomain.com、dowload.yourdomain.com 和 publicaccess.yourdomain.com。所以你可能会考虑使用通配符证书......但您也有 secure.yourdomain.com 或 Finance.yourdomain.com - 即使在不同的服务器上。然后 publicaccess.yourdomain.com 将能够冒充 secure.yourdomain.com...虽然在某些情况下这可能是可以的,但通常您需要一些权限分离......
目前能想到的就这么多了,以后可能会再编辑一下……
至于什么时候使用 SSL/TLS 是一个坏主意 - 如果您拥有不适合特定受众(单个用户或注册会员)的公共信息,并且您并不特别希望他们专门从正确的来源(例如股票代码值必须来自经过身份验证的来源...) - 那么就没有真正的理由产生开销(而不仅仅是性能...)开发/测试/证书/等)。
但是,如果您有共享资源(例如同一服务器)在您的站点和另一个更敏感的站点之间,那么更敏感的站点应该在此处设置规则。
此外,密码(和其他凭据)、信用卡信息等应始终通过 SSL/TLS。
确保在 HTTPS 页面上时,页面上的所有元素都来自 HTTPS 地址。这意味着元素应该具有相对路径(例如“/images/banner.jpg”)以便继承协议,或者您需要在每个页面上进行检查以找到协议,并将其用于所有元素。
注意:这包括所有外部资源(例如 Google Analytics javascript 文件)!
我能想到的唯一缺点是它增加了浏览器和服务器的处理时间(几乎可以忽略不计)。我建议只加密需要的传输。
我想说,使用启用 SSL 的网站时最常见的错误是
- 该网站错误地将用户从页面重定向到 http 作为 https
- 必要时网站不会自动切换到 https
- https 页面上的图像和其他资源正在通过 http 加载,这将触发浏览器的安全警报。确保所有资产都使用指定 https 的完全限定 URI。
- 安全证书仅适用于一个子域(例如 www),但您的站点实际上使用了多个子域。如果需要,请确保获得通配符证书。
我会随时建议 任何 用户数据存储在数据库中并使用 https 进行通信。即使用户数据很平常,也要考虑此要求,因为即使许多这些日常细节也被该用户用来在其他网站上识别自己的身份。考虑银行询问您的所有随机安全问题(例如您住在哪条街上?)。这可以很容易地从地址字段中获取。在这种情况下,数据不是您所认为的密码,但也可能是。此外,您永远无法预测哪些用户数据将用于其他地方的安全问题。您还可以预期,以普通网络用户(想想您的祖母)的智力,这些信息可能会在其他地方构成该用户密码的一部分。
如果您使用 https,则指向一个指针
使得如果用户输入http://www.website-that-needs-https.com/etc/yadda.php他们会自动重定向到https://www.website-that-needs-https.com/etc/yadda.php(个人厌恶)
然而,如果您只是做一个纯 html 网页,那本质上是从服务器到用户的单向信息传输,不用担心。
这里都是非常好的提示...但我只是想添加一些东西..
我见过一些网站为您提供 http 登录页面,并且仅在您发布用户名/密码后将您重定向到 https。这意味着在建立 https 连接之前,用户名会以明文形式传输。
简而言之,创建从 ssl 登录的页面,而不是发布到 ssl 页面。
我发现试图 <link>
不存在的样式表也会引起安全警告。当我使用正确的路径时,会出现锁定图标。