Web安全是前端开发人员常常忽略的主题。当咱们评估网站的质量时,咱们一般会查看性能,SEO友好性和可访问性等指标,而网站抵御恶意攻击的能力却经常被忽略。即便敏感的用户数据存储在服务器端,后端开发人员也必须采起重要措施来保护服务器,但最终,保护数据的责任在后端和前端之间共享。虽然敏感数据可能被安全地锁在后端仓库中,但前端掌握着前门的钥匙,窃取它们一般是得到访问权限的最简单方法。html
后端和前端之间共同承担保护用户数据的责任。
恶意用户能够采起多种攻击手段来破坏咱们的前端应用程序,可是幸运的是,咱们只需使用几个正确配置的响应头并遵循良好的开发实践,就能够在很大程度上减轻此类攻击的风险。在本文中,我将介绍10种简单的操做,能够经过这些简单的操做来改善对Web应用程序的保护。前端
在咱们开始改善网站安全性以前,重要的一点是要对咱们所作更改的有效性提供反馈。虽然量化构成“良好开发实践”的内容可能比较困难,可是能够至关准确地度量安全头的强度。就像咱们使用Lighthouse获取性能,SEO和可访问性分数同样,咱们可使用 SecurityHeaders.com根据当前响应头获取安全分数。node
SecurityHeaders能够给咱们的最高分是“A+”,咱们应该始终为此努力。git
处理响应头曾经是后端的任务,可是现在,咱们常常将Web应用程序部署到Zeit或Netlify等“无服务器”云平台,并配置它们以返回正确的响应标头成为前端责任。确保了解你的云托管提供商如何使用响应头,并进行相应配置。web
下面来看一下具体的安全措施有哪些。后端
完善的内容安全策略(CSP)是前端应用程序安全的基石。CSP是浏览器中引入的一种标准,用于检测和缓解某些类型的代码注入攻击,包括跨站点脚本(XSS)和点击劫持。浏览器
强CSP能够禁用可能有害的内联代码执行,并限制加载外部资源的域。能够经过将 Content-Security-Policy
头设置为以分号分隔的指令列表来启用CSP。若是你的网站不须要访问任何外部资源,一个良好的头的起始值多是这样的:安全
Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self'; connect-src 'self';
在这里,咱们将script-src
、img-src
、style-src
和 connect-src
指令设置为 self
,以指示全部脚本、图像、样式表和fetch调用都应该被限制在HTML文档提供服务的同一来源。其余任何未明确说起的CSP指令将回退到 default-src
指令指定的值。咱们将其设置为 none
表示默认行为是拒绝任何URL的链接。服务器
然而,现在几乎任何web应用程序都不是独立的,因此你可能要调整这个头,以便你可使用其余信任域,如域名Google Fonts或AWS S3 bucket,但始终最好从如下开始最严格的政策,并在须要时稍后放宽。前端工程师
您能够在MDN网站上找到CSP指令的完整列表。
若是用户输入确实注入了恶意代码,咱们能够经过提供 "X-XSS-Protection": "1; mode = block"
头指令来指示浏览器阻止响应。
尽管大多数现代浏览器默认状况下都启用了XSS保护模式,而且咱们也可使用内容安全策略来禁用内联JavaScript,但仍建议包含 X-XSS-Protection
头,以确保不使用内联JavaScript的旧版浏览器具备更好的安全性。
点击劫持是一种攻击,网站A上的用户被诱骗对网站B执行某些操做。为了实现这一点,恶意用户将网站B嵌入到一个不可见的iframe中,而后将iframe放置在网站A上毫无防备的用户的光标之下,所以当用户单击,或者更确切地说,认为他们单击了网站A上的元素时,他们其实是单击了网站B上的某个东西。
咱们能够经过提供 X-Frame-Options
响应头来防止此类攻击,该响应头禁止在框架中呈现网站:
"X-Frame-Options": "DENY"
另外,咱们可使用frame-ancestors
CSP指令,该指令能够更好地控制父级能够或不能将页面嵌入iframe的程度。
良好的安全作法的一部分是,限制对正确使用咱们的网站所不须要的任何内容的访问。咱们已经使用CSP应用了这个原则来限制网站能够链接的域的数量,可是它也能够应用到浏览器特性上。
咱们可使用 Feature-Policy
头指示浏览器拒绝访问咱们的应用不须要的某些功能和API。
咱们将 Feature-Policy
设置为由分号分隔的一串规则,其中每一个规则都是功能的名称,后跟其策略名称。
"Feature-Policy": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none';"
Smashing Magazine上有一篇很棒的文章,详细介绍了功能策略,但大多数状况下,您但愿为全部不使用的特性设置 none
。
当你点击一个连接,从你的网站导航,目的地网站将收到你的网站上最后一个位置的URL在一个 referrer
头。该URL可能包含敏感数据和半敏感数据(例如会话令牌和用户ID),这些数据永远都不该公开。
为了防止referrer
值泄漏,咱们将 Referrer-Policy
标头设置为 no-referrer
:
"Referrer-Policy": "no-referrer"
在大多数状况下,这个值应该是不错的,可是若是您的应用程序逻辑要求您在某些状况下保留 referrer
,请查看Scott Helme撰写的这篇文章,在这篇文章中,他分解了全部可能的头值以及什么时候应用它们。
跨站点脚本攻击能够经过许多不一样的DOM API进行,其中恶意代码被注入到网站中,可是最经常使用的是 innerHTML
。
咱们永远不该基于用户未过滤的输入来设置 innerHTML
。用户能够直接操做的任何值——输入字段中的文本、URL中的参数或本地存储项——都应该首先进行转义和清除。理想状况下,使用textContent而不是innerHTML能够彻底避免生成HTML输出。若是确实须要为用户提供富文本编辑,请使用专业的第三方库。
不幸的是,innerHTML
并非DOM API的惟一弱点,并且容易受到XSS注入攻击的代码仍然难以检测。这就是为何必定要有一个严格的不容许内联代码执行的内容安全策略。
诸如React,Vue和Angular之类的现代UI框架内置了良好的安全性,能够很大程度上消除XSS攻击的风险。它们自动对HTML输出进行编码,减小对XSS敏感DOM API的使用,并为潜在危险的方法(如dangerouslySetInnerHTML
)提供明确而谨慎的名称。
快速浏览一下 node_modules
文件夹,就会确认咱们的web应用程序是由数百(若是不是数千)个依赖项组成的lego拼图。确保这些依赖项不包含任何已知的安全漏洞对于网站的总体安全很是重要。
确保依赖关系保持安全和最新的最佳方法是使漏洞检查成为开发过程的一部分。为此,您能够集成Dependabot和Snyk之类的工具,这些工具将为过期或潜在易受攻击的依赖项建立提取请求,并帮助您更快地应用修补程序。
第三方服务如Google Analytics、Intercom、Mixpanel等,能够为您的业务需求提供“一行代码”的解决方案。同时,它们会使你的网站更容易受到攻击,由于若是第三方服务受到损害,那么你的网站也会受到损害。
若是你决定集成第三方服务,请确保设置最强大的CSP策略,该策略仍将容许该服务正常运行。大多数流行的服务都记录了它们要求的CSP指令,所以请确保遵循其准则。
在使用Google Tag Manager、Segment或任何其余容许组织中任何人集成更多第三方服务的工具时,应该特别注意。有权使用此工具的人员必须了解链接其余服务的安全隐患,而且最好与开发团队进行讨论。
对于您使用的全部第三方脚本,请确保在可能的状况下包括 integrity
属性。浏览器具备 Subresource Integrity 功能,该功能能够验证您正在加载的脚本的加密哈希,并确保它未被篡改。
你的 script 标签以下所示:
<script src="https://example.com/example-framework.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>
值得说明的是,此技术对第三方库有用,但对第三方服务的做用较小。大多数状况下,当你为第三方服务添加脚本时,该脚本仅用于加载另外一个从属脚本。没法检查依赖脚本的完整性,由于能够随时对其进行修改,所以在这种状况下,咱们必须依靠严格的内容安全策略。
原文:https://levelup.gitconnected.com/10-security-tips-for-frontend-developers-19e3dd9fb069
做者:Konstantin Lebedev
若是对你有所启发和帮助,能够点个关注、收藏、转发,也能够留言讨论,这是对做者的最大鼓励。
做者简介:Web前端工程师,全栈开发工程师、持续学习者。