如何使用 HTTP Headers 来保护你的 Web 应用

原文地址:How To Secure Your Web App With HTTP Headers
原文作者:Hagay Lupesko
众所周知,无论是简单的小网页还是复杂的单页应用,Web 应用都是网络攻击的目标 。2016 年,这种最主要的攻击模式 —— 攻击 web 应用,造成了大约 40% 的数据泄露 。事实上,现在来说,了解网络安全并不是锦上添花,而是 Web 开发者的必需任务,特别对于构建面向消费者的产品的开发人员 。
开发者可以利用 HTTP 响应头来加强 Web 应用程序的安全性,通常只需要添加几行代码即可 。本文将介绍 web 开发者如何利用 HTTP Headers 来构建安全的应用 。虽然本文的示例代码是 Node.js,但基本所有主流的服务端语言都支持设置 HTTP 响应头,并且都可以简单地对其进行配置 。
关于 HTTP Headers技术上来说,HTTP 头只是简单的字段,以明文形式编码,它是 HTTP 请求和响应消息头的一部分 。它们旨在使客户端和服务端都能够发送和接受有关要建立的连接、所请求的资源,以及返回的资源本身的元数据 。
【如何使用 HTTP Headers 来保护你的 Web 应用】可以简单地使用 cURL --head 来检查纯文本 HTTP 响应头,例如:
$ curl --head https://www.google.comHTTP/1.1 200 OKDate: Thu, 05 Jan 2017 08:20:29 GMTExpires: -1Cache-Control: private, max-age=0Content-Type: text/html; charset=ISO-8859-1Transfer-Encoding: chunkedAccept-Ranges: noneVary: Accept-Encoding…复制代码现在,数百种响应头正在被 web 应用所使用,其中一部分由互联网工程任务组(IETF)标准化 。IETF 是一个开放性组织,今天我们所熟知的许多 web 标准和专利都是由他们推进的 。HTTP 头提供了一种灵活可扩展的机制,造就了现今的网络各种丰富多变的用例 。
机密资源禁用缓存缓存是优化客户端-服务端架构性能中有效的技术,HTTP 也不例外,同样广泛利用了缓存技术 。但是,在缓存的资源是保密的情况下,缓存可能导致漏洞,所以必须避免 。假设一个 web 应用对含有敏感信息的网页进行缓存,并且是在一台公用的 PC 上使用,任何人可以通过访问浏览器的缓存看到这个 web 应用上的敏感信息,甚至有时仅仅通过点击浏览器的返回按钮就可以看到 。
IETF RFC 7234 中定义了 HTTP 缓存,指定 HTTP 客户端(浏览器以及网络代理)的默认行为:除非另行指定,否则始终缓存对 HTTP GET 请求的响应 。虽然这样可以使 HTTP 提升性能减少网络拥塞,但如上所述,它也有可能使终端用户个人信息被盗 。好消息是,HTTP 规范还定义了一种非常简单的方式来指示客户端对特定响应不进行缓存,通过使用 —— 对,你猜到了 —— HTTP 响应头 。
当你准备返回敏感信息并希望禁用 HTTP 客户端的缓存时,有三个响应头可以返回:

  • Cache-Control
从 HTTP 1.1 引入的此响应头可能包含一个或多个指令,每个指令带有特定的缓存语义,指示 HTTP 客户端和代理如何处理有此响应头注释的响应 。我推荐如下指定响应头,cache-control: no-cache, no-store, must-revalidate 。这三个指令基本上可以指示客户端和中间代理不可使用之前缓存的响应,不可存储响应,甚至就算响应被缓存,也必须从源服务器上重新验证 。
  • Pragma: no-cache
为了向后兼容 HTTP 1.0,你还需要包含此响应头 。有部分客户端,特别是中间代理,可能仍然没有完全支持 HTTP 1.1,所以不能正确处理前面提到的 Cache-Control 响应头,因此使用 Pragma: no-cache 确保较旧的客户端不缓存你的响应 。
  • Expires: -1
此响应头指定了该响应过期的时间戳 。如果不指定为未来某个真实时间而指定为 -1,可以保证客户端立即将此响应视为过期并避免缓存 。
需要注意的是,禁用缓存提高安全性及保护机密资源的同时,也的确会带来性能上的折损 。所以确保仅对实际需要保密性的资源禁用缓存,而不是对服务器的任何响应禁用 。想要更深入了解 web 资源缓存的最佳实践,我推荐阅读 Jake Archibald 的文章 。
下面是 Node.js 中设置响应头的示例代码:
function requestHandler(req, res) {res.setHeader('Cache-Control','no-cache,no-store,max-age=0,must-revalidate');res.setHeader('Pragma','no-cache');res.setHeader('Expires','-1');}复制代码强制 HTTPS今天,HTTPS 的重要性已经得到了技术界的广泛认可 。越来越多的 web 应用配置了安全端点,并将不安全网路重定向到安全端点(即 HTTP 重定向至 HTTPS) 。不幸的是,终端用户还未完全理解 HTTPS 的重要性,这种缺乏理解使他们面临着各种中间人攻击(MitM) 。普通用户访问到一个 web 应用时,并不会注意到正在使用的网络协议是安全的(HTTPS)还是不安全的(HTTP) 。甚至,当浏览器出现了证书错误或警告时,很多用户会直接点击略过警告 。


推荐阅读