Pragma: no-cache
为了向后兼容 HTTP 1.0,你还需要包含此响应头。有部分客户端,特别是中间代理,可能仍然没有完全支持 HTTP 1.1,所以不能正确处理前面提到的 Cache-Control 响应头,因此使用 Pragma: no-cache 确保较旧的客户端不缓存你的响应。
Expires: -1
此响应头指定了该响应过期的时间戳。如果不指定为未来某个真实时间而指定为 -1,可以保证客户端立即将此响应视为过期并避免缓存。
需要注意的是,禁用缓存提高安全性及保护机密资源的同时,也的确会带来性能上的折损。所以确保仅对实际需要保密性的资源禁用缓存,而不是对服务器的任何响应禁用。
下面是 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 的重要性已经得到了技术界的广泛认可。越来越多的 web网站应用配置了安全端点,并将不安全网路重定向到安全端点(即 HTTP 重定向至 HTTPS)。不幸的是,终端用户还未完全理解 HTTPS 的重要性,这种缺乏理解使他们面临着各种中间人攻 击(MitM)。普通用户访问到一个 web网站应用时,并不会注意到正在使用的网络协议是安全的(HTTPS)还是不安全的(HTTP)。甚至,当浏览器出现了证书错误或警 告时,很多用户会直接点击略过警 告。
与 web网站应用进行交互时,通过有效的 HTTPS 连接是非常重要的:不安全的连接将会使得用户露在各种攻 击之下,这可能导致 cookie 被盗甚至更糟。举个例子,攻击者可以在公共 Wi-Fi 网络下轻易骗取网络帧并提取那些不使用 HTTPS 的用户的会话 cookie。更糟的情况是,即使用户通过安全连接与 web 应用进行交互也可能遭受降级攻 击,这种攻 击试图强制将连接降级到不安全的连接,从而使用户受到中间人攻击。
我们如何帮助用户避免这些攻击,并更好地推行 HTTPS 的使用呢?使用 HTTP 严格传输安全头(HSTS)。简单来说,HSTS 确保与源主机间的所有通信都使用 HTTPS。RFC 6797 中说明了,HSTS 可以使 web 应用程序指示浏览器仅允许与源主机之间的 HTTPS 连接,将所有不安全的连接内部重定向到安全连接,并自动将所有不安全的资源请求升级为安全请求。
HSTS 的指令如下:
max-age=
此项指示浏览器对此域缓存此响应头指定的秒数。这样可以保证长时间的加固安全。
includeSubDomains
此项指示浏览器对当前域的所有子域应用 HSTS,这可以用于所有当前和未来可能的子域。
preload
这是一个强大的指令,强制浏览器始终安全加载你的 web 应用程序,即使是第一次收到响应之前加载!这是通过将启用 HSTS 预加载域的列表硬编码到浏览器的代码中实现的。要启用预加载功能,你需要在 Google Chrome 团队维护的网站 HSTS 预加载列表提交注册你的域。
注意谨慎使用 preload,因为这意味着它不能轻易撤销,并可能更新延迟数个月。虽然预加载肯定会加强应用程序的安全性,但也意味着你需要充分确信你的应用程序仅支持 HTTPS!
我建议的用法是 Strict-Transport-Security: max-age=31536000; includeSubDomains;,这样指示了浏览器强制通过 HTTPS 连接到源主机并且有效期为一年。如果你对你的 app 仅处理 HTTPS 很有信心,我也推荐加上 preload 指令,当然别忘记去前面提到的预加载列表注册你的网站。
以下是在 Nodes.js 中实现 HSTS 的方法:
function requestHandler(req, res){
res.setHeader('Strict-Transport-Security','max-age=31536000; includeSubDomains; preload');
}
启用 XSS 过滤
在反射型跨站脚本攻 击(reflected XSS)中,攻 击者将恶意 JavaScript 代码注入到 HTTP 请求,注入的代码「映射」到响应中,并由浏览器执行,从而使恶意代码在可信任的上下文中执行,访问诸如会话 cookie 中的潜在秘密信息。不幸的是,XSS 是一个很常见的网络应用攻击,且令人惊讶地有效!
为了了解反射型 XSS 攻击,参考以下 Node.js 代码,渲染 mywebapp.com,模拟一个简单的 web 应用程序,它将搜索结果以及用户请求的搜索关键词一起呈现:
function handleRequest(req, res) {
res.writeHead(200);
// Get the search term const parsedUrl = require('url').parse(req.url);
const searchTerm = decodeURI(parsedUrl.query); const resultSet = search(searchTerm); // Render the document res.end(
"" +"" +
"
You searched for: " + searchTerm + "
" +
// Search results rendering goes here… "" +
"");
};
为了保护用户应对反射型 XSS 攻 击,有些浏览器实施了保护机制。这些保护机制尝试通过在 HTTP 请求和响应中寻找匹配的代码模式来辨识这些攻 击。Internet Explorer 是第一个推出这种机制的,在 2008 年的 IE 8 中引入了 XSS 过滤器的机制,而 WebKit 后来推出了 XSS 审计。
现今在 Chrome 和 Safari 上可用(Firefox 没有内置类似的机制,但是用户可以使用插件来获得此功能)。这些保护机制并不完美,它们可能无法检测到真正的 XSS 攻击(漏报),在其他情况可能会阻止合法代码(误判)。由于后一种情况的出现,浏览器允许用户可设置禁用 XSS 过滤功能。不幸的是,这通常是一个全局设置,这会完全关闭所有浏览器加载的 web 应用程序的安全功能。
幸运的是,有方法可以让 web 应用覆盖此配置,并确保浏览器加载的 web 应用已打开 XSS 过滤器。即通过设定 X-XSS-Protection 响应头实现。此响应头支持 Internet Explorer(IE8 以上)、Edge、Chrome 和 Safari,指示浏览器打开或关闭内置的保护机制,及覆盖浏览器的本地配置。
X-XSS-Protection 指令包括:
1 或者 0
使用或禁用 XSS 过滤器。
mode=block
当检测到 XSS 攻击时,这会指示浏览器不渲染整个页面。
我建议永远打开 XSS 过滤器以及 block 模式,以求最大化保护用户。这样的响应头应该是这样的:
X-XSS-Protection: 1; mode=block
以下是在 Node.js 中配置此响应头的方法:
function requestHandler(req, res){
res.setHeader('X-XSS-Protection','1;mode=block');}