《大型网站技术架构》笔记
# 《大型网站技术架构》笔记
# 1. 大型网站架构模式
为解决高并发、海量数据处理,实现高性能、高可用、易伸缩、可扩展、安全等各种架构目标,从而逐步形成大型网站架构模式。
# 1.1 分层
将系统在横向业务上分为几个部分,各部分负责单一职责,上层对下层的依赖和调用组成一个完整的系统。分层便于分工合作开发与维护,难点在于边界划分。网站分层架构:
层 | 功能 |
---|---|
应用层 | 负责具体业务和视图展示,如网站首页 |
服务层 | 为应用层提供服务支持,如用户管理 |
数据层 | 提供数据存储访问服务,如数据库、缓存、文件、搜索引擎等 |
# 1.2 分割
就是系统拆分,将不同功能和服务分割开啦,包装成高内聚低耦合的模块单元,有助于软件的开发和维护,同时也便于分布式部署,提高网站并发能力和功能扩展能力。
大型网站的分割力度会很小。比如在应用层,购物、轮胎、搜索、广告分割成不同的应用,由独立的团队负责,部署在不同服务器上。如果一个应用内部业务庞大且复杂,可以加进行分割。比如购物业务可以继续分割成机票酒店业务,3C 业务和小商品业务等。在这个粒度上还可以继续分割称首页、搜索列表、商品详情等模块。同样,服务层也可以分割。
# 1.3 分布式
对于大型网站,分割和分层的目的是为了切分后的模块便于分布式部署,通过远程调用协同工作。分布式意味着使用更多的计算机完成同样的功能,能够处理的并发量和数据量就越大。
但分布式也带来了问题:
- 网络性能对分布式带来影响
- 可用性降低
- 很难保持一致性
- 分布式事务难以保证
常用分布式方案:
- 分布式应用和服务:提高并发性、减少数据库资源消耗、加速开发和发布、应用复用共同的服务便于业务扩展
- 分布式静态资源:动静分离,静态资源如 JS,CSS,图片等独立分布式部署,减轻应用服务器压力
- 分布式数据和存储:大型网站需处理海量数据,除了传统数据库分布式部署外,还有 NoSQL 分布式部署
- 分布式计算:将计算分发到数据所在的位置加速计算和分布式计算
# 1.4 集群
使用分布式将分层和分割的模块独立部署,但是对于用户集中访问的模块(网站首页),还需要独立部署的服务器集群化,即多台服务器部署相同的业务构成一个集群,通过负载均衡设备共同对外提供服务。提高了并发性和可用性。
# 1.5 缓存
缓存就是将数据存放在距离计算最近的位置加速处理速度。
- CDN:内容分发网络,部署在距离终端用户最近的网络服务商,用户的网络请求总是先到达他的服务商那里,在哪里缓存网站的一些静态资源(较少变化的数据),可以就近以最快的速度返回给用户。
- 反向代理:反向代理属于网站前端架构的一部分,部署在网站的前端,当用户请求到达网站的数据中心时,最先访问的反向代理服务器,这里缓存网站的静态资源,无需将请求继续转发给应用服务器就能返回用户。
- 本地缓存:在应用服务器本地缓存热点数据,可以在本机内存中直接访问数据,无法访问数据库。
- 分布式缓存:Redis 集群
# 1.6 异步
系统解耦的手段除了分层、分割、分布式,还有异步,业务之间的消息传递不是同步调用,而是将一个业务操作分层多个阶段,每个阶段之间通过共享数据的方式异步执行进行协助。单一服务器内可以通过多线程共享内存队列实现异步,分布式系统中可以通过 MQ 实现异步。
- 提高可用性:消费者故障了,生产者也可以继续往消息队列里发消息
- 加快响应:生产者处理完业务,将消息写入消息队列即可返回
- 消除并发高峰:突然增加的访问请求访问消息队列,等待消费者服务器依次处理。
# 1.7 冗余
为了服务24小时连续运行且不丢失数据,需要服务器冗余运行,数据冗余备份。访问和负载很小的服务器也必须部署至少两台服务器构成集群,通过冗余实现服务高可用。数据库定期备份,存档保存,冷备份加热备份。
为了抵御海啸、地震等不可抗力导致网站完全瘫痪,还需要全球范围内部署灾备数据中心。网站程序和数据实时同步到多个灾备数据中心。
# 1.8 自动化
自动化架构设计主要集中在发布运维方面。通过减少人为干预,使发布过程自动化可有效减少故障。
- 自动化代码管理
- 自动化测试
- 自动化安全检测
- 自动化部署
- 自动化监控
- 自动化报警
- 自动化失效转移
- 自动化失效回复
- 自动化降级
- 自动化资源分配
# 1.9 安全
通过密码和手机校验进行身份认证;登录、交易等交易需要对网络通信进行加密,从网站上获取敏感数据进行加密处理;为防止脚本滥用网站资源需使用验证码进行识别;对于常见网站攻击要进行预防;对于垃圾信息、敏感信息进行过滤……
# 2. 大型网站核心架构要素
除了系统功能外,软件架构还需要关注性能、可用性、伸缩性、扩展性和安全性。
# 3. 高性能
网站的性能问题很多是在用户高并发访问时产生的,所以网站性能优化的主要工作时改善高并发用户访问情况下网站的响应速度。
# 3.1 网站性能测试
# 3.1.1 性能指标
响应时间:执行一个操作需要的时间,从发出请求到响应数据所需时间,直观反映系统快慢。
并发数:系统能够同时处理请求数目, 反应系统负载特性。网站系统用户数 >> 网站用户在线人数 >> 网站并发用户数
吞吐量:单位时间内系统处理的请求处理,体现系统的整体处理能力,TPS(每秒事务数),HPS(每秒 HTTP 请求数),QPS(每秒查询数)等。
性能计数器:描述系统性能的一些指标,包括 System Load、对象和线程数、内存使用、CPU 使用、磁盘与网络 IO 等指标。
# 3.1.2 性能测试方法
分为性能测试、负载测试、压力测试、稳定性测试。
- 性能测试:以系统设计初期规划的性能指标为预期目标,对系统不断施压,验证系统在资源可接受范围内,能否达到性能预期。
- 负载测试:对系统不断地增加并发请求以增加系统压力,直到系统的某项或多项新年指标达到安全临界值。此时再继续施压,系统处理能力将下降。
- 压力测试:超过安全负载情况,继续施压,直到系统崩溃或不能再处理任何请求,获得系统最大压力承受能力。
- 稳定性测试:在特定硬件、软件、网络环境下,给系统施加不均匀的业务压力,使系统较长运行一段时间,以此检测系统是否稳定。
性能测试是一个不断对系统增加访问压力,以获得系统性能指标、最大负载能力、最大压力承受能力的过程。增加压力,就是不断的增加并发数量 ,性能测试遵循下图的抛物线规律。
性能测试反应的使系统在实际生产环境中使用时,随着用户并发 访问数量的增加,系统的处理能力。
# 3.2 Web 前端性能优化
Web 前端指网站业务逻辑之前的部分,包括浏览器架子啊、网站视图模型、图片服务、CDN 服务等,主要优化手段有优化浏览器访问、使用反向代理、CDN 等。
# 3.2.1 浏览器访问优化
- 减少 http 请求:合并 js、css、图片等
- 使用浏览器缓存:css、js、图片等更新频率低的缓存在浏览器上
- 启用压缩:减少通信传输的数据量
- CSS 放在页面最上面,JS 放在页面最下面:浏览器下载完全部 CSS 才会对整个页面渲染,所以要尽早下载;JS 加载后会立刻执行,可能会阻塞造成页面缓慢。
- 减少 Cookie 传输:每次请求都需要携带 cookie,太大的 cookie 严重影响性能。
# 3.2.2 CDN 加速
CDN,Content Distribute Network,内容分发网络,本质上是缓存,将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓的网络第一跳。
CDN 部署在网络运营商的机房,这些运营商是终端用户网络服务的提供商,因此用户请求路由的第一跳就到达了 CDN 服务器,CDN 存在改请求资源时立即返回浏览器,减少路径返回响应,加快响应速度。
CDN 可以缓存一般的静态资源,如图片、文件、CSS、JS、静态网页等。这些文件访问频率很高,可以极改善网页打开速度。
# 3.2.3 反向代理
除了安全功能,代理服务器也可以通过配置缓存功能加快 Web 请求。用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上。当其他用户访问该静态内容时,就可以直接从反向代理服务器返回,加速 Web 请求响应速度,减轻 Web 服务器压力。
# 3.3 应用服务器性能优化
应用服务器时处理网站业务的服务器,网站的业务代码都部署在这里,时网站开发最复杂,变化最多的地方,优化手段主要有缓存、集群、异步等。
# 3.3.1 分布式缓存
网站性能优化第一定律:优先考虑使用缓存优化性能
# 3.3.2 异步操作
消息队列通过异步操作实现削峰作用。
# 3.3.3 使用集群
高并发场景下,使用负载均衡技术为一个应用构建由多态服务器组成的服务器集群,将并发访问请求分发到多太服务器上处理。
# 3.3.4 代码优化
⭐ 多线程
使用多线程的原因:IO 阻塞与多 CPU
启动线程数 = [ 任务执行时间 / (任务执行时间 - IO 等待时间) ] * CPU 内核数
最佳启动线程数和 CPU 内核数量成正比,和 IO 等待时间成正比。如果任务都是 CPU 计算型,那么线程数量最多不要超过 CPU 内核数;如果是 IO 型,那么线程数量可以大于 CPU 核数。
解决线程安全:对象设计为无状态、使用局部对象、并发问资源时使用锁
⭐ 资源复用
系统运行时,要尽量减少那些开销很大的系统资源的创建和销毁,比如数据库连接、网络通信连接、线程、复杂对象等。从编程角度,资源复用主要有两种模式:单例和对象池。
⭐ 数据结构
程序 = 数据结构 + 算法,比如 Hash 表数据结构
⭐ 垃圾回收
避免 Full GC,即全量回收,根据业务特点和对象的生命周期合理设置年轻代和老年代大小,尽量减少 Full GC。事实上,某些 Web 应用在整个运行期间可以做到从不进行 Full GC。
# 3.4 存储性能优化
- 机械硬盘 VS 固态硬盘
- B+ 树 VS LSM 树
- RAID(廉价磁盘冗余阵列) VS HDFS
# 4. 高可用
# 4.1 可用性度量
网站不可用也被称作网站故障,通常用多少个 9 来衡量网站的可用性,如 QQ 的可用性是 4 个 9,即 99%。
网站不可用时间(故障时间)= 故障修复时间点 - 故障发现(报告)时间点
网站年度可用性指标 = (1 - 网站不可用时间 / 年度总时间)* 100%
# 4.2 高可用网站架构
高可用架构的主要手段是数据和服务的冗余备份及失效转移,一旦某些服务器宕机,就将服务器切换到其他可用的服务器上。
典型的分层模型:应用层、服务层、数据层
比如某网站的文库、贴吧、百科等不同产品部署在各自独立的服务器集群上,互不干扰;这些产品依赖一些共同的业务,如登陆服务、账户服务等,这些可复用的业务服务也各自部署在独立的服务器集群上。至于数据库、文件服务、缓存服务、搜索服务等数据存储与访问服务都部署在各自独立的服务器集群上。
应用层的服务器通常为了应对高并发的访问请求,会通过负载均衡设备将一组服务器组成一个集群共同对位提供服务。
服务层的服务器情况与应用层的服务器类似,也是通过集群方式实现高可用,至少这些服务器被应用层通过分布式服务调用框架访问。
数据层的服务器上存储数据,为了保证数据不丢失、不中断,需要在数据写入时进行数据同步复制。
# 4.3 高可用的应用
应用层主要处理网站应用的业务逻辑,也称作逻辑层,显著的特点是无状态性,应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行相应的业务逻辑处理,多个服务实例之间完全对等。
无状态给高可用的架构设计带来巨大便利,当集群中的服务器是无状·态对等时,负载均衡可起到事实上高可用的作用。
session 管理服务器,用 redis 集群就可以。
# 4.4 高可用的服务
可复用的服务模块为业务产品提供基础公共服务,大型网站中这些服务通常都独立分布式部署,被具体应用远程调用,也是无状态服务。
高可用的服务策略:
- 分级管理:核心应用和服务优先使用更好的硬件;服务部署在服务器上要进行必要的隔离,避免故障的连锁反应。
- 超时设置:在应用程序中设置调用的超时时间,一旦超时,通信框架就抛出异常。
- 异步调用:应用对服务的调用通过消息队列实现异步,避免一个服务失败导致整个应用请求失败。
- 服务降级:网站高峰期,因大量并发调用可能会导致性能下降。为保证核心应用和功能的正常运行,需要对服务进行降级
- 拒绝服务:拒绝低优先级应用的调用,或者随机拒绝部分请求,避免要死大家一起死的惨剧。
- 关闭功能:关闭部分不重要的服务,双十一期间关闭评价、确认收货等非核心业务。
- 幂等性设计:服务的重复调用是不可避免的,因此必须保证重复调用和一次调用产生相同的结果。有些服务天然幂等性,比如用户性别设置为男性;例如转账等操作需要在调用服务的时候进行校验。
# 4.5 高可用的数据
保证网站的数据就是保护企业的命脉。
保障数据存储高可用的手段主要是数据备份和失效转移机制。数据备份就是保证数据有多个副本,任意副本的失效都不会导致数据的永久丢失;失效转移则保证当一个数据副本不可访问时i,可用快速切换访问数据的其他版本。
为了保证数据的高可用,在 CAP 原理中,只能实现 AP,放弃 C,只能保证 C 的最终一致性。
# 4.5.1 数据备份
早期数据的备份主要是数据冷备,即定期将数据复制到某种存储介质上并物理存档保存,如果系统存储损坏,就从冷备的存储设备中回复。但冷备不能保证数据最终一致性,也不能保证数据可用性,从冷备中恢复数据需要较长时间,而这段时间无法访问数据,系统也是不可用。
数据热备,可用提供更好的数据可用性,分为异步热备和同步热备。
异步方式是指多分数据副本的的写入操作异步完成,数据写入时,由主存储服务器的写操作代理模块将数据写入本机存储系统后立即返回写操作成功响应,然后通过异步线程将ixe操作数据同步到从存储服务器。
同步方法时指多份数据的写入操作同步完成,即应用程序收到数据服务系统写成功响应时,多分数据都已经写操作成功。但若收到失败响应时,可能有部分副本或全部副本都已经写成功了,因为网络或系统故障无法返回操作成功的响应。
关系型数据库热备机制通过主从同步机制,不仅解决数据备份问题,还可改善数据库性能。实践中,通常使用读写分离的方法访问 Slave 和 Master 数据库,写操作只访问 Master 数据库,读操作只访问 Slave 数据库。
# 4.5.2 失效转移
失效转移由三部分组成:失效确认、访问转移、数据恢复
失效确认:系统确认一台服务是否宕机的手段有两种:心跳检测和应用程序访问失败报告。
访问转移:确认某台数据存储服务器宕机后,需要架构数据的读写访问重新路由到其他服务器上。
数据恢复:宕机恢复后,数据服务数目要恢复到系统的设定值。
# 4.6 网站发布的高可用
相当于要求给飞行中的飞机换个引擎,即不能让飞机剧烈摇晃(影响用户体验),也不能让飞机降落(系统停机维护),更不能让飞机坠毁(系统故障网络不可用)。
网站的发布过程事实上和服务器宕机效果相当,其对系统可用性的影响也和服务器宕机相似。
发布过程可以先关闭一部分服务,并将新的代码同步到这些服务器上并启动,之后逐渐同步其他服务器并启动。逐步完成整个系统的更新。
# 4.6.1 自动化测试
代码上线前需要进行严格的测试,防止引入未预料到的 Bug,可以使用自动测试工具或脚本完成测试。
# 4.6.2 预发布验证
即使经过严格的测试,软件部署到线上服务器还是会遇到各种问题,其原因是测试环境和生产环境不同导致的。因此网站发布时,可以先把测试通过的代码发布到预发布机器(线上服务器)上,执行一些经典的业务流程,确认系统没问题后再正式发布。
预发布服务器是一种特殊的服务器,它和线上正式服务器唯一的不同就是没有配置在负载均衡服务器上,外部用户无法访问。
应用网站强调的一个处理错误的理念是快速失败,即如果系统在启动时发现问题就立刻抛出异常,停止启动让工程师介入排查错误,而不是启动后执行错误的操作。
# 4.6.3 代码控制
代码版本控制
# 4.6.4 自动化发布
基于火车发布模型实现自动化发布流程。
# 4.6.5 灰度发布
大型网站会使用灰度发布模式,将集群服务器分为若干部分,每天只发布一部分服务器,观察运行稳定没有故障后在继续发布一部分服务器,持续几天才把整个集群全部发布完毕,期间如果发现问题,只需要回滚已发布的一部分服务器即可。
灰度发布也常用于用户测试,即在部分服务器上发布新版本,其余服务器保持老版本,然后监控用户行为,收集用户体验报告,对比满意度后确认最终发布版本。
# 4.7 网站运行监控
"不允许没有监控的系统上限",这许多网站架构师在做项目上限评审时常说的一句话。
# 4.7.1 监控数据采集
- 用户行为日志收集:操作环境、系统、浏览器版本信息、IP、页面访问路径、停留时间等等
- 服务端日志收集:开启日志功能
- 客户端浏览器日志手机:嵌入专门的 JS 脚本手机日志
- 服务器性能监控:监控系统负载、内存、磁盘、磁盘 IO、网络 IO 等,提早发现问题提早解决。
- 运行数据报告:监控一些与具体业务场景相关的技术和业务指标,如缓存命中率、平均延迟实践、每分钟发送的邮件数目、待处理的任务总数等。
# 4.7.2 监控管理
监控数据采集后,可以根据数据进行风险预警,并对服务器进行失效转移、自动负载挑战、最大化利用集群所有机器的资源。
- 系统报警:如果某一项指标超出阈值就需要报警通知相关人员,及时采取措施。
- 失效转移:监控系统发现故障的情况下主动通知应用,进行失效转移。
- 自动优雅降级:优雅降至是指网站应付突然爆发的访问高峰,主动关闭部分功能,释放部分系统资源,保证网站核心功能正常访问。
# 5. 伸缩性
网站的伸缩性是指不需要改变网站软硬件设计,仅仅通过改变部署的服务器数量就可以扩大或者缩小网站的服务处理能力。最重要的技术手段就是使用服务器集群,通过不断地向集群中添加服务器增强整个集群的处理能力。当网站具有很好的伸缩性,活动期间向服务器集群中加入更多服务器以满足用户访问,活动结束后将这些服务器下线以节约成本。
网站系统的伸缩架构,只要技术上能做到向集群中加入服务器的数量和集群的处理能力成线性关系,那么就可以以此为技术手段不断提升自己的规模,从一个服务几十人的小型网站发展成服务几亿人的大型网站。
# 5.1 伸缩性设计
分为两类
- 根据功能进行物理分离实现伸缩,不同服务器部署不同服务,提供不同的功能。
- 单一功能通过集群部署实现伸缩,集群内的多态服务器部署相同的服务,提供相同的功能。
# 5.1.1 不同功能进行物理分离实现伸缩
通过物理分离不同的网站功能,实现网站伸缩性的手段,具体分为两种情况:
- 纵向分离(分层后分离):将业务处理流程上的不同部分分离部署。如,网站具体产品 - 可复用业务服务 - 基础技术服务 - 数据库
- 横向分离(业务分割后分离):将不同的业务模块分离部署,如,网站前台 - 卖家后台 - 卖家后台 - 交易论坛。
我觉得这两种分离方式应该时结合使用的。
# 5.1.2 单一功能通过集群规模实现伸缩
当单一的服务器不能满足业务规模的需求,需使用服务器集群,即将相同服务部署在多态服务器上构成一个集群整体对外提供服务。
当一头牛拉不动车的时候,不是要找一头更强壮的牛,而是用两头牛拉车。
集群伸缩性分为应用服务器集群的伸缩性和数据服务器集群伸缩性。
# 5.2 应用服务器集群的伸缩性设计
应用服务器应该是无状态的,所以可以使用负载均衡将请求分发到不同的服务器上。所以,负载均衡不仅实现网站的伸缩性,同时还改善网站的可用性。
# 5.2.1 HTTP 重定向负载均衡
HTTP 重定向服务器是一台普通的应用服务器,根据用户的HTTP 请求计算一台真实的 Web 服务地址,并将该 Web 服务地址写入 HTTP 重定向响应中(状态码302)返回给用户浏览器。缺点时浏览器需要两次请求才能万次一次访问,性能差,并且重定向服务器自身的处理能力可能成为瓶颈,整个集群的伸缩规模有限。
# 5.2.2 DNS 域名解析负载均衡
利用 DNS 处理域名解析请求的同时进行负载均衡,每次域名解析请求都会根据负载均衡算法计算一个不同的 IP 地址返回。
优点:将负载均衡的工作转交给 DNS,省掉了网站管理维护负载均衡服务器的麻烦,DNS 会将域名解析成距离用户地理位置最近的一个服务器地址,加快用户访问速度,改善性能。
缺点:DNS 缓存 A 记录,当某服务器下线后,即使修改了 DNS 的 A 记录,要使其生效也需要较长时间,这段时间 DNS 依然会将域名解析到已经下线的服务器,导致用户无法访问。
# 5.2.3 反向代理负载均衡
通过反向代理服务器做负载均衡,因为转发请求在 HTTP 协议层面,因此也叫应用层负载均衡。
# 5.2.4 IP 负载均衡
在网络层通过修改请求目标地址进行负载均衡。集群吞吐量受限于负载均衡服务器网卡带宽。
# 5.2.5 数据链路层负载均衡
在数据链路层修改 mac 地址进行负载均衡,又称作三角传输模式,负载均衡分发过程中不修改 IP 地址,只修改目的 mac 地址。
使用三角传输模式的链路层负载均衡是目前大型网站使用最广的一种负载均衡手段。
# 5.2.6 负载均衡算法
- 轮询(Round Robin,RR)
- 加权轮询(Weighted Round Robin,WRR)
- 随机(Random)
- 最少连接数(Least Connections)
- 源地址散列(Source Hashing):根据 IP 进行 hash,保证同一 IP 的请求到达统一服务器
# 5.3 分布式缓存集群的伸缩性设计
分布式缓存的一致性 Hash 算法
# 5.4 数据存储服务器集群的伸缩性设计
# 5.4.1 关系型数据库集群的伸缩性设计
主从复制,读写分离,主服务器负责写,从服务器负责读,主服务器上写的数据复制到从服务器上。
除了数据库读写分离,分割模式也可以用在数据库上,不同业务数据表部署在不同的数据库集群上,即数据分库,不过跨库的表不能进行 join 操作。在大型网站中,即使进行了分库和主从复制,对一些单表数据仍然很大,还需要进行分片,将一张表拆开分别存储在多个数据库中。
支持数据分片的分布式关系数据库产品有 Cobar。(感觉用的不多,不研究了)
# 5.4.2 NoSql 数据库的伸缩性设计
....
高手定律:这个世界上只有遇不到的问题,没有解决不了的问题,高手之所以成为高手,是因为他们遇到了常人很难遇到的问题,并解决了。
# 6. 可扩展性
伸缩性(Scalability)
指系统能通过增加或减少自身资源规模的方式增强或减少自己计算处理事务的能力。
扩展性(Extensibility)
指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。它是系统架构设计层面的开闭原则,架构设计考虑未来功能扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。
低耦合的系统更容易扩展,低耦合的模块更容易复用,一个低耦合的系统设计也会让开发过程和维护变得更加轻松和容易管理。软件架构师的价值在于将一个大系统切分成 N 个低耦合的子模块的能力,这些子模块包含横向的业务模块,也包含纵向的基础技术模块。
⭐ 消息队列降低耦合
利用消息队列的发布 — 订阅模式工作,生产者发布消息,一个或多个消费者消费消息。生产者和消费者之间没有直接的耦合。
⭐ 利用分布式服务打造可复用的业务平台
巨无霸系统有如下问题:
- 编译、部署困难
- 代码分支管理困难
- 数据库连接耗尽
- 新增业务困难
解决方案:拆分
- 纵向拆分:将大型应用拆分出小应用
- 横向拆分:将复用的业务拆分出来独立部署,
# 7. 安全性
# 7.1 攻击与防御
# 7.1.1 XSS 攻击
XSS,Cross Site Script,跨站点脚本攻击,篡改网页,恶意注入 HTML 脚本,在用户浏览网页时,控制用户浏览器进行恶意操作。
反射型:攻击者诱使用户点击一个嵌入恶意脚本的连接,达到攻击目的。
持久型:黑客提交含有恶意脚本的请求,保存在被攻击的 Web 站点的数据库中,用户浏览网页时,恶意脚本被包含在正常页面中,达到攻击目的 。
解决:
- 消毒:对某些 html 危险字符转义,如 ”>“ 转移为 ”>“。
- HttpOnly:禁止页面 JS 访问带有 HttpOnly 属性的 Cookie
# 7.1.2 注入攻击
注入攻击:SQL 注入攻击和 OS 注入攻击。
- SQL 注入攻击:在 HTTP 请求中注入恶意 SQL 命令,服务器用请求参数构造数据库 SQL 命令时,恶意 SQL 被一起构造,并在数据库中执行。攻击者对数据库结构有所了解才能进行,攻击者获取数据库表结构的手段有:
- 开源:开源项目搭建的网站
- 错误回显:网站开启错误回显,服务器内部 500 错误会显示到浏览器上,攻击者通过非法参数使服务端异常信息输出到浏览器端,为攻击猜测数据库表结构提供了遍历。
- 盲注:攻击者根据页面变化情况判断 SQL 语句的执行情况,据此猜测数据库表结构。
- 防御手段:
- 消毒:通过正则匹配沟渠请求参数中可能注入的 SQL,如
drop table
、\b(?:update\b.*?\best|delete\b\W*?\from)\b
等。 - 参数绑定:使用预编译手段,攻击者的恶意 SQL 会被当做 SQL 的参数,而不是 SQL 命令被执行。
- 消毒:通过正则匹配沟渠请求参数中可能注入的 SQL,如
# 7.1.3 CSRF 攻击
CSRF,Cross Site Request Forgery,跨站点请求伪造,攻击者通过跨站请求,以合法用户的身份进行非法操作,如转账交易、发表评论等。CSRF 的主要手段使利用跨站请求,在用户不知情的情况下,以用户的身份伪造请求。其核心是利用了浏览器 Cookie 或服务器 Session 策略,盗用用户信息。
防御手段:
- 表单 Token:在页面表单中增加一个随机数作为 Token,每次响应页面的 Token 都不相同,从正常页面提交的请求会包含该 Token 值,而伪造的请求无法获得该值,服务器检查请求参数中 Token 的值是否存在并且正确以确定请求提交者是否合法。
- 验证码
- Referer check:HTTP 请求头中的 Referer 域中记录着请求来源,可通过检查请求来源,验证其是否合法。
# 7.1.4 其他
- Error Code:错误回显,通过查看服务器端的错误信息来分析出系统漏洞并进行攻击。
- HTML 注释:HTML 的注释给黑客造成攻击遍历。
- 文件上传:黑客上传可执行文件,并在服务器端执行,那么攻击者可以为所欲为。
# 7.2 加密
# 7.2.1 单项散列加密
通过不同输入长度的信息进行散列计算,得到固定长度的输出,该计算过程是单向的。
利用这个特性,可以进行密码加密保存,即用户注册时输入的密码不直接保存到数据库,而是对密码进行单向散列加密,将密文存入数据库,用户登陆时,通过输入的密码算出密文,与数据库中的密文进行比较,如果一致则密码验证成功。即使被拖库,也不会泄露用户密码。
为了加强单项散列的安全性,还会给散列算法加盐,增加破解的难度。
常用算法有:MD5、SHA 等。
# 7.2.2 对称加密
加密和解密使用同一个密钥。
# 7.2.3 非对称加密
加密和揭秘使用的密钥不同,其中一个对外界公开,称作公钥,另一个只有持有者直到,被称作私钥。公钥加密的信息必须用私钥解开,用私钥加密的信息只能用公钥解开。