网站性能优化和安全

Web性能、安全及SEO
性能优化及安全篇
感谢网上有那么多的分享blog,讲的挺详细的,有了一个很全面的了解。

网站性能

从输入URL到页面加载,总体来说分为以下几个过程:
  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束

反应给客户的直观感觉就是一个页面打开的速度,但这时间所受的影响因素很多,网络兆宽,页面、软件打开多少占据内存等等。
常见网站性能指标:

  • 白屏时间
  • 首屏时间
  • 整页时间
  • DNS时间
  • CPU占用率

对前端来说,处理的有限,可以从以下一些方面做处理优化。

content方向:
  1. 减少HTTP请求:合并文件、CSS精灵、inline Image
  2. 减少DNS查询:DNS查询完成之前浏览器不能从这个主机下载任何文件。方法:DNS缓存、将资源分布到恰当数量的主机名,平衡并行下载和DNS查询
  3. 避免重定向:多余的中间访问
  4. 使Ajax可缓存
  5. 非必须组件延迟加载
  6. 未来所需组件预加载
  7. 减少DOM元素数量
  8. 将资源放到不同的域下:浏览器同时从一个域下载资源的数目有限,增加域可以提高并行下载量
  9. 减少iframe数量
  10. 减少404页面
Server方面
  1. 使用CDN
  2. 添加Expires或者Cache-Control响应头
  3. 对组件使用Gzip压缩
  4. 配置ETag
  5. Flush Buffer Early
  6. Ajax使用GET进行请求
  7. 避免空src的img标签
Cookie方面
  1. 减小cookie大小
  2. 引入资源的域名不要包含cookie
css方面
  1. 将样式表放到页面顶部
  2. 不使用CSS表达式
  3. 使用不使用@import
  4. 不使用IE的Filter
Javascript方面
  1. 将脚本放到页面底部
  2. 将javascript和css从外部引入
  3. 压缩javascript和css
  4. 删除不需要的脚本
  5. 减少DOM访问
  6. 合理设计事件监听器
图片方面
  1. 优化图片:根据实际颜色需要选择色深、压缩
  2. 优化css精灵
  3. 不要在HTML中拉伸图片
  4. 保证favicon.ico小并且可缓存
  5. 使用字体图标
  6. 图片进行懒加载
  7. 合理的设置缓存

网站安全

一般常见的Web攻击都是下三个方法:

  1. XSS(Cross-Site Scripting,跨站脚本攻击):指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JS进行的一种攻击。
  2. SQL注入攻击
  3. CSRF(跨站点请求伪造):指攻击者通过设置好的陷阱,强制对已完成的认证用户进行非预期的个人信息或设定信息等某些状态更新
XSS(跨站脚本攻击)

XSS,即 Cross Site Script,中译是跨站脚本攻击;其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS。
XSS 攻击是指攻击者在网站上注入恶意的客户端代码,通过恶意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行控制或者获取用户隐私数据的一种攻击方式。
攻击者对客户端网页注入的恶意脚本一般包括 JavaScript,有时也会包含 HTML 和 Flash。有很多种方式进行 XSS 攻击,但它们的共同点为:将一些隐私数据像 cookie、session 发送给攻击者,将受害者重定向到一个由攻击者控制的网站,在受害者的机器上进行一些恶意操作。

a. 持久型 XSS

持久型 XSS 就是对客户端攻击的脚本植入到服务器上,从而导致每个正常访问到的用户都会遭到这段 XSS 脚本的攻击。(如在留言评论功能添加恶意脚本)

b. 非持久型 XSS

非持久型 XSS 是对一个页面的 URL 中的某个参数做文章,把精心构造好的恶意脚本包装在 URL 参数中,再将这个 URL 发布到网上,骗取用户访问,从而进行攻击
非持久性 XSS 的安全威胁比较小,因为只要服务器调整业务代码进行过滤,黑客精心构造的这段 URL 就会瞬间失效了,而相比之下,持久型 XSS 的攻击影响力很大,有时候服务端需要删好几张表,查询很多库才能将恶意代码的数据进行删除。

XSS 攻击的防范

1.HttpOnly 防止劫取 Cookie

浏览器将禁止页面的Javascript 访问带有 HttpOnly 属性的Cookie。
上文有说到,攻击者可以通过注入恶意脚本获取用户的 Cookie 信息。通常 Cookie 中都包含了用户的登录凭证信息,攻击者在获取到 Cookie 之后,则可以发起 Cookie 劫持攻击。所以,严格来说,HttpOnly 并非阻止 XSS 攻击,而是能阻止 XSS 攻击后的 Cookie 劫持攻击。

2. 输入检查

对于用户的任何输入要进行检查、过滤和转义。建立可信任的字符和 HTML 标签白名单,对于不在白名单之列的字符或者标签进行过滤或编码。
在 XSS 防御中,输入检查一般是检查用户输入的数据中是否包含 <,>等特殊字符,如果存在,则对特殊字符进行过滤或编码,这种方式也称为 XSS Filter。
而在一些前端框架中,都会有一份 decodingMap, 用于对用户输入所包含的特殊字符或标签进行编码或过滤,如<,>,script,防止 XSS 攻击:

// vuejs 中的 decodingMap
// 在 vuejs 中,如果输入带 script 标签的内容,会直接过滤掉
const decodingMap = {
  '<': '<',
  '>': '>',
  '"': '"',
  '&': '&',
  '
': '\n'
}
3.输出检查

用户的输入会存在问题,服务端的输出也会存在问题。一般来说,除富文本的输出外,在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御 XSS 攻击。例如利用 sanitize-html 对输出内容进行有规则的过滤之后再输出到页面中。

CSRF(跨站点请求伪造)

CSRF,即 Cross Site Request Forgery,中译是跨站请求伪造,是一种劫持受信任用户向服务器发送非预期请求的攻击方式。
未被授权的系统想要有权访问某个资源的情况(跨站点请求伪造),首先会伪装自己,让处理请求的服务器认为他是合法的。收到CSRF 攻击的Ajax 程序有大有小,目的是:

  • 恶意的数据窃取和数据销毁

通常情况下,CSRF 攻击是攻击者借助受害者的 Cookie 骗取服务器的信任,可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

攻击方法

假设有一个 bbs 站点:http://www.c.com,当登录后的用户发起如下 GET 请求时,会删除 ID 指定的帖子:

http://www.c.com:8002/content/delete/:id

如发起 http://www.c.com:8002/content/delete/87343请求时,会删除 id 为 87343 的帖子。当用户登录之后,会设置如下 cookie:

res.setHeader('Set-Cookie', ['user=22333; expires=Sat, 21 Jul 2018 00:00:00 GMT;']);

user 对应的值是用户 ID。然后构造一个页面 A:

CSRF 攻击者准备的网站:

页面 A 使用了一个img标签,其地址指向了删除用户帖子的链接,当登录用户访问攻击者的网站时,会向 www.c.com 发起一个删除用户帖子的请求。此时若用户在切换到 www.c.com的帖子页面刷新,会发现ID 为 87343 的帖子已经被删除。

由于 Cookie 中包含了用户的认证信息,当用户访问攻击者准备的攻击环境时,攻击者就可以对服务器发起 CSRF 攻击。在这个攻击过程中,攻击者借助受害者的 Cookie 骗取服务器的信任,但并不能拿到 Cookie,也看不到 Cookie 的内容。而对于服务器返回的结果,由于浏览器同源策略的限制,攻击者也无法进行解析。因此,攻击者无法从返回的结果中得到任何东西,他所能做的就是给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的值,而非窃取服务器中的数据。
但若 CSRF 攻击的目标并不需要使用 Cookie,则也不必顾虑浏览器的 Cookie 策略了。

CSRF攻击防范

1. 验证码

验证码被认为是对抗 CSRF 攻击最简洁而有效的防御方法。
从上述示例中可以看出,CSRF 攻击往往是在用户不知情的情况下构造了网络请求。而验证码会强制用户必须与应用进行交互,才能完成最终请求。因为通常情况下,验证码能够很好地遏制 CSRF 攻击。
但验证码并不是万能的,因为出于用户考虑,不能给网站所有的操作都加上验证码。因此,验证码只能作为防御 CSRF 的一种辅助手段,而不能作为最主要的解决方案。

2. Referer Check

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。通过 Referer Check,可以检查请求是否来自合法的"源"。
比如,如果用户要删除自己的帖子,那么先要登录 www.c.com,然后找到对应的页面,发起删除帖子的请求。此时,Referer 的值是http://www.c.com;当请求是从 www.a.com 发起时,Referer 的值是 http://www.a.com了。因此,要防御 CSRF 攻击,只需要对于每一个删帖请求验证其 Referer 值,如果是以www.c.com 开头的域名,则说明该请求是来自网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是 CSRF 攻击,可以拒绝该请求。

if (req.headers.referer !== 'http://www.c.com:8002/') {
    res.write('csrf 攻击');
    return;
}

Referer Check 不仅能防范 CSRF 攻击,另一个应用场景是 “防止图片盗链”。

3. 添加 token 验证

CSRF 攻击之所以能够成功,是因为攻击者可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 Cookie 中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的 Cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入攻击者所不能伪造的信息,并且该信息不存在于 Cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

SQL注入

什么是SQL注入

就是通过把 SQL 命令插入到 Web 表单提交或页面请求的查询字符串,最终达到服务器执行恶意的 SQL 命令
具体来说,它是利用现有应用程序,将(恶意) 的 SQL 命令注入到后台数据库引擎执行的能力,它可以通过在 Web 表单中输入 (恶意) SQL 语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行 SQL 语句。

SQL注入的危害
  • 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。
  • 网页篡改:通过操作数据库对特定网页进行篡改。
  • 数据库被恶意操作:数据库服务器被攻击
  • 服务器被远程控制,被安装后门
  • 删除和修改数据库信息
SQL 防护
  • 永远不要信任用户的输入: 对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和双"-"进行转换等。
  • 永远不要使用动态拼装 SQL,可以使用参数化的 SQL 或者直接使用存储过程进行数据查询存取。
  • 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
  • 不要把机密信息直接存放,加密或者 hash 掉密码和敏感的信息。

防御方法

1. 数据校验

其实漏洞的主要原因还是没有对用户输入的数据进行过滤,所以对来自用户的数据(GET, POST, cookie 等)最好做到以下两种过滤校验:
检查输入的数据是否具有所期望的数据格式。这种在参数是数字的时候特别有效,如果攻击者选择在参数中插入内容的话则会被转换成 NaN 导致攻击失败。在 ThinkJS 中我们提供了强大的 Logic 功能可以方便的对数据进行格式校验。
使用数据库特定的敏感字符转义函数把用户提交上来的非数字数据进行转义。在 ThinkJS 中封装了 escapeString() 方法可以对敏感字符进行转义,其原理则和 PHP 的 mysql_escape_string() 方法是一致的。

2. 权限限制

严格限制Web应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害。请记住永远不要使用超级用户或所有者帐号去连接数据库!当数据库被攻击时将损伤限制在当前表的范围是比较明智的选择。通过权限限制可以防止攻击者获取数据库其它信息,甚至利用数据库执行 Shell 命令等操作。

3. 日志处理

当数据库操作失败的时候,尽量不要将原始错误日志返回,比如类型错误、字段不匹配等,把代码里的 SQL 语句暴露出来,以防止攻击者利用这些错误信息进行 SQL 注入。除此之外,在允许的情况下,使用代码或数据库系统保存查询日志也是一个好办法。显然,日志并不能防止任何攻击,但定期审计数据库执行日志可以跟踪是否存在应用程序正常逻辑之外的 SQL 语句执行。日志本身没用,要查阅其中包含的信息才行。毕竟,更多的信息总比没有要好。

SEO

SEO优化要注意的事项:

  1. 合理的title、description、keywords:
    title值强调重点即可,重要关键词出现不要超过2次,而且要靠前,不同页面title要有所不同;
    description把页面内容高度概括,长度合适,不可过分堆砌关键词,不同页面description有所不同;
    keywords列举出重要关键词即可
  2. 语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
  3. 重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,有的
    搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
  4. 重要内容不要用js输出:爬虫不会执行js获取内容
  5. 少用iframe:搜索引擎不会抓取iframe中的内容
  6. 非装饰性图片必须加alt
  7. 提高网站速度:网站速度是搜索引擎排序的一个重要指标

标签语义化的优势:

  1. 去掉样式后页面呈现清晰的结构
  2. 盲人使用读屏器更好地阅读
  3. 搜索引擎更好地理解页面,有利于收录
  4. 便于团队项目的可持续运作及维护

你可能感兴趣的:(网站性能优化和安全)