Web通用笔记整理

Web通用

更新ing
相当部分知识收集于网络,经过个人理解加工而成。

1. XSS原理攻防

1.1 概述

Cross Site Scripting:跨站脚本

为什么不用CSS,名字已经被用了。X代表扩展含义。

XSS即跨站脚本攻击,最普遍的Web应用安全漏洞。使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中。当正常用户访问页面时,可导致嵌入的恶意脚本代码执行,从而达到恶意攻击用户的目的。比如获取cookie,sessionID等。

原理:

就是当动态页面插入的内容中含有特殊字符比如<>这样的,浏览器会误认为插入了html标签,当这些标签引入了一段script脚本时,脚本程序就会在浏览器中执行。

综上,只要这些特殊字符不能被动态页面检查或者检查出现失误时,就会产生XSS漏洞。

类似SQL注入

类型

  • 持久型跨站,最直接的危害类型,跨站代码存储在服务器(数据库)。

  • 非持久型跨站,反射型跨站脚本漏洞,最普遍的类型。用户访问服务器-跨站链接-返回跨站代码。

    攻击者事先制作好攻击链接,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。

  • DOM跨站(DOM XSS),客户端脚本处理逻辑导致的安全问题。基于DOM的XSS漏洞是指受害者端的网页脚本在修改本地页面DOM环境时未进行合理的处置,使得攻击脚本被执行。在整个攻击过程中,服务器响应的页面并没有发生变化,引起客户端脚本执行结果差异的原因是对本地DOM的恶意篡改利用。

攻击方式:

  1. 盗用cookie(比如document.cookie),获取敏感信息
  2. 利用植入Flash,通过crossdomain权限设置进一步获取更高权限
  3. 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击者)用户的身份执行一些管理操作,或执行一些一般的比如发微博、加好友、发私信等操作。
  4. 利用可被攻击的域受到其他域信任这一特点,以受信任来源的身份请求一些平时不允许的操作,比如进行不当的投票活动。
  5. 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。

1.2 心得体会

本质:

  1. 恶意代码未经过滤,和正常代码混在一起,浏览器都给执行了。

  2. 又由于直接在用户的终端执行,所以能直接获取用户信息,然后利用这些信息冒充用户向网站发起攻击者定义的请求。

  3. 在部分情况下由于输入的限制,注入的恶意脚本一般比较短。但可以通过引入外部脚本并由浏览器执行,来完成比较复杂的攻击策略。

持久化:

因为脚本直接被保存到了服务器(数据库)上,所以,所有用户浏览时都会读取到该恶意脚本,进而执行。

2. CSRF

Cross-site request forgery

跨站请求伪造

https://www.freebuf.com/articles/web/118352.html

核心本质:利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。它与XSS区别在于,它没有盗取cookie,而是直接利用,“冒充用户”

一个攻击过程

  1. 受害者登录a.com,保留了登录凭证(Cookie)
  2. 攻击者引诱受害者访问了b.com
  3. b.com向a.com发送了一个请求,a.com/act=xx。浏览器会默认携带a.com的cookie。
  4. a.com收到请求后,对请求进行验证,确认是受害者的凭证,误以为是受害者自己发送的请求。
  5. a.com以受害者的名义执行了act=xx
  6. 攻击完成。攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了攻击者定义的操作。

CSRF防护策略

大多来自第三方网站,就直接禁止外域(不受信任的域名)对我们发起请求。

在部分与CSRF有关的请求中,请求的header中会携带Origin字段。字段内包含请求的域名(不包含path及query)。如果Origin存在,那么直接使用Origin中的字段来确认来源域名即可。

CSRF token

它之所以能够攻击成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带了正确的Token,来把正常的请求和攻击的请求区分开。

  1. 首先,用户打开页面,服务器给该用户生成一个Token。每次页面加载时,用JS遍历整个DOM树,对DOM中所有的a和form标签后面加入Token。
  2. 页面提交的请求携带这个Token
  3. 服务端验证Token是否有效。当用户从客户端得到了Token,再次提交给服务器时,服务器判断Token的有效性。验证过程时先解密Token,对比加密字符串以及时间戳,如果加密字符串一致且事件没过期,则该Token有效。

3. 浏览器

参考:
https://kb.cnblogs.com/page/129756/

3.1 浏览器主要功能

将用户选择的web资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中。资源格式通常为HTML,也包括pdf、image等其他格式。

3.2 主要构成

  1. 用户界面

包括地址栏、后退、前进按钮、书签目录等。即我们所能看到的,除了用来显示我们所请求页面的主窗口之外的其他部分。

  1. 浏览器引擎

用来查询及操作渲染引擎的接口。

  1. 渲染引擎

用来显示请求的内容。例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来。

  1. 网络

用于完成网络调用。比如http请求,它具有平台无关的接口,可在不同平台上工作。

  1. UI后端

用于绘制类似组合选择框及对话框等基本组件,句有不特定于某个平台的通用接口,底层使用操作系统的用户接口。

  1. JS解释器

用于解释执行JS代码

  1. 数据存储

属于持久层。浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术

浏览器主要组件如图。

3.3 渲染引擎

3.3.1 概述

职责就是渲染,就是在浏览器窗口中显示所请求的内容。

默认可以显示html、xml文档及图片,也可以借助插件来显示其他数据。比如pdf等。

两种渲染引擎——

Firefox使用Geoko。这是Mozilla自主研发的渲染引擎

Chrome和Safari都使用webkit。这是一款开源渲染引擎,原本为linux平台开发,后来由apple移植到mac及windows上。

3.3.2 渲染流程

渲染引擎首先要通过网络获得所请求文档的内容,通常以8K分块的方式完成。

获取内容之后才进入基本流程:

  1. 解析html以构建DOM树

  2. 构建render树

  3. 布局render树

  4. 绘制render树

  5. 渲染引擎解析html,将标签转化为内容树中的dom节点。紧接着,解析外部css文件以及style标签中的样式信息。这些样式信息以及html终得可见性指令将被用来构建另一棵树——render树。

  6. render树由一些包含有颜色和大小等属性的矩形组成,它们将被按照正确顺序显示到屏幕上。

  7. render树构建完毕后,会执行布局过程,它将确定每个节点在屏幕上的确切坐标。

  8. 然后绘制,即遍历render树,并使用UI后端层绘制每个节点。

注意:这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早地将内容呈现到屏幕上,并不会等到所有的html都解析完毕后再去构建和布局render树。它是解析完一部分就显示一部分内容,同时可能还在通过网络下载其余内容。

该图为webkit主流程图。Geoko与它不一样。

3.4 解析与DOM树构建

Parsing and DOM tree construction

3.4.1 解析

解析一个文档,即将其转换为具有一定意义地结构——编码可以理解和使用地东西。解析的结果通常是表达文档结构的借点树,称为解析树或语法树。

详情有点类似编译原理中的文法解析,略复杂,此处暂略。

总之理解为:就是把html和css的文件中代码,解析成可以用的树。

3.5 渲染树构建

render tree construction

当DOM树构建完成时,浏览器开始构建另一棵树——渲染树。渲染树由元素显示序列中的可见元素组成,它是文档的可视化表示,构建这棵树是为了以正确的顺序绘制文档内容。

Firefox将渲染树中的元素成为iframe,而webkit则用renderer或渲染对象来描述这些元素。

一个渲染对象知道如何布局以及绘制自己及它的children。

RenderObject是Webkit的渲染对象基类。

每个渲染对象用一个和该节点的CSS盒模型相对应的矩形区域来表示。盒模型的类型受该节点相关的display样式属性的影响。

  • 渲染树和DOM树的关系

渲染对象和DOM元素相对应,但这种对应不是一对一的,不可见的DOM元素不会被插入渲染树,比如head元素。display属性为none的元素也不会在渲染树中出现。(然而,visibility属性为hidden的元素会出现在渲染树中。)

有一些DOM元素对应几个可见对象,它们一般是一些具有复杂结构的元素,无法用一个矩形来描述。比如select元素有三个渲染对象——一个显示区域、一个下拉列表和一个按钮。

一些渲染对象和所对应的DOM节点不在树上相同的位置。比如:浮动和绝对定位的元素在文本流之外,在两棵树上的位置不同,渲染树上标识出真实的结构,并用一个占位结构标识出它们原来的位置。

  • 创建树的流程

Webkit中,计算样式并生成渲染对象的过程称为attachment,每个DOM节点有一个attach方法,attachment的过程是同步的,调用新节点的attach方法将节点插入到DOM树中。

处理html和body标签将构建渲染树的根。这个根渲染对象的大小就是viewport——浏览器窗口的显示区域,webkit称之为RenderView,这个就是 文档所指向的渲染对象,树中其他的部分都将作为一个插入的DOM节点被创建。

3.6 布局

当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout或reflow。

布局是一个递归的过程,由根渲染对象开始,它对应html文档元素,布局继续递归地通过一些或所有的frame层级,为每个需要几何信息的渲染对象进行计算。根渲染对象的位置是0,0,它的大小是viewport——浏览器窗口的可见部分。

3.7 绘制

绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件,这在UI的章节有更多的介绍。

3.8 动态变化

浏览器总是试着以最小的动作响应一个变化,所以一个元素颜色的变化将只导致该元素的重绘,元素位置的变化将导致元素的布局和重绘,添加一个DOM节点,也会导致这个元素的布局和重绘。

3.9 渲染引擎的线程

渲染引擎是单线程的,除了网络操作以外,几乎所有事情都在单一的线程中处理,在Firefox和Safari中,这是浏览器的主线程,Chrome中这是tab的主线程。

网络操作由几个并行线程执行,并行连接的个数是有限的。

  • 事件循环

浏览器主线程是一个事件循环,它被设计为无线循环以保持执行过程的代码可用,等待事件(比如layout和paint事件)并执行它们。

4. 浏览器缓存

说白了就是利用本地存储,把一部分数据保存在客户端,减少对服务器的请求,降低服务器压力,提升网页加载速度。

宏观分类:

  • 共有缓存

能被各级代理缓存的缓存

  • 私有缓存

用户专项的,各级代理不能缓存的缓存

微观分类:

  • 浏览器缓存
  • 代理服务器缓存
  • CDN缓存
  • 数据库缓存
  • 应用层缓存

4.1 http缓存

缓存位置:

  • Service Worker(独立线程,可实现缓存功能,协议必须为https)
  • Memory Cache(内存缓存,一旦关闭tab页面,内存缓存就释放)
  • Disk Cache
  • Push Cache(推送缓存,Http/2的内容)
4.1.1 强缓存
  • 不会向服务器发请求,而是直接从缓存中读取资源

  • 请求返回200的状态码

  • 在chrome控制台的network选项中可以看到size显示from disk cache或from memory cache。

强缓存的两种实现方式:

设置两种HTTP Header,即:Expires和Cache-Control

(注意:浏览器接收到资源后,会把该资源联通所有的response header一起缓存下来。)

浏览器读取缓存的顺序就是memory->disk。

当js和图片等文件解析执行后,浏览器会把这些直接存入内存缓存中,那么当刷新页面时只需要直接从内存中读取;而CSS文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存。

response header中有这样一个属性:cache-control。这是http/1.1的重要规则,用于控制网页的缓存。(Expires是http/1.0的。当以cache-control优先)

4.1.2 协商缓存

当强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。

  • 协商缓存生效,返回304和Not Modified

  • 协商缓存失效,返回200和请求结果

  • Last-Modified和If-Modified-Since

浏览器第一次访问资源时,服务器返回资源的同时会在响应头中添加Last-Modified,意为该资源在服务器上的最后修改时间。浏览器接收后缓存文件和header。下一次请求该资源时,浏览器检测到有Last-Modified这个header,就添加If-Modified-Since这个header,值就是Last-Modified中的值,发给服务器。服务器再次收到该资源的请求,根据If-Modified-Since中的值与服务器中该资源的最后修改时间进行对比,如果没有变化,就返回304和空的响应体,直接从缓存读取;如果If-Modified-Since中的值早于服务器的最后修改时间,说明文件有更新,就返回新的资源文件和200。

缺点:它以秒作为单位,某些服务端不能获取精确的修改时间。

  • ETag和If-None-Match

Etag是上一次加载资源时,服务器返回的响应头,是对该资源的一种唯一标识。只要资源有变化,ETag就会重新生成。浏览器在下一次加载该资源向服务器发送请求时,会将上一次返回的ETag值放到请求头中的If-None-Match里,服务器只需要比较客户端传来的If-None-Match和自己服务i去上该资源的ETag是否一致,就可以判断资源相对客户端而言是否被修改过。如果服务器发现ETag匹配不上,就直接以常规GET 200回包形式将新的资源(包括新的ETag)发给客户端;如果ETag一致,就直接返回304通知客户端直接用本地缓存即可。

  • 两种协商缓存对比
  1. 在精确度上,ETag优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1s内修改了很多次,那么其Last-Modified其实并没有体现出修改,但是ETag每次都会改变,保证了精度。如果是负载均衡的服务器,各个服务器生成的Last-Modified也可能不一致。
  2. 性能上,Etag逊于Last-Modified。因为后者只需要记录时间,而前者需要服务器通过算法来计算一个hash值。
  3. 优先级上,服务器校验优先考虑Etag。

4.2 缓存机制

强制缓存优先于协商缓存进行。如果强缓存(Expires和Cache-Control)生效则直接用缓存,若不生效则进行协商缓存(Last-Modified/If-Modified-Since和ETag/If-None-Match)。协商缓存由服务器决定是否使用缓存,若协商缓存失效,则代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。

Q:如果什么缓存策略都没设置,浏览器会如何处理?

在这种情况下,浏览器会采用一个启发式的算法,通常取响应头中的Data减去Last-Modified值的10%作为缓存时间。

4.3 实际应用缓存策略

4.3.1 对于频繁变动的资源
Cache-Control: no-cache

该设置可以使浏览器每次都请求服务器,然后配合ETag或者Last-Modified来验证资源是否有效。这样做法虽然无法节省请求数量,但能显著减少响应数据大小。

4.3.2 对于不常变化的资源
Cache-Control: max-age=31536000

在处理这类资源时,通常给它们的Cache-Control设置一个很大的max-age=31536000(一年),这样浏览器之后请求相同的URL会命中强缓存。为了解决更新的问题,需要在文件名(或者路径)中添加hash、版本号等动态字符,之后更改动态字符,来达到更改引用URL的目的,让之前的强缓存不再被使用。

4.3.3 用户行为

指的是用户在操作浏览器时,会触发怎样的缓存策略,主要有三种。

  • 打开网页,地址栏输入地址:查找disk cache中是否有匹配。如果有则使用,如果没有则发送网络请求。
  • 普通刷新(F5):因为TAB没有关闭,因此memory cache可用,若匹配的话会被优先使用,其次是disk cache。
  • 强制刷新(Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有Cache-control: no-cache(为了兼容还有Pragma: no-cache),服务器直接返回200和最新内容。

4.4 本地存储

本地存储主要有:localStorage、sessionStorage和cookie、WebSql和IndexDB。

4.4.1 Cookie

Cookie主要是由服务器生成,前端也可以设置,保存在客户端本地的一个文件。通过response响应头的set-Cookie字段进行设置,且Cookie的内容自动在请求的时候被传递给服务器,在客户端和服务器之间来回传递。

Cookie包含的信息:可以记录你的用户ID、密码、浏览过的网页、停留的事件等。当再次来到该网站时,网站通过读取Cookies,得知你的想关信息做出相应动作,比如让你不用输入ID、密码就直接登录等。

一个网站只能读取它自己放置的信息,不能读取其他网站的cookie文件。

因此,Cookie文件还保存了host属性,即网站的域名或ip。

这些属性以名值对的方式进行保存,内容大多进行了加密处理。

Cookie文件的命名格式:用户名@网站地址[数字].txt

Cookie优点:

  • 给用户更人性化的体验,比如记住密码等功能。
  • 弥补HTTP无连接的特性
  • 站点统计访问人数的一个依据

Cookie缺点:

  • 无法解决多人共用一台电脑的问题,带来了不安全因素
  • Cookie文件容易被误删
  • Cookies欺骗。修改host文件,可以非法访问目标站点的Cookie
  • 容量限制,不能超过4KB

4.4.2 localStorage

一般是前端开发人员在前端设置,一旦数据保存在本地后,就可以避免再向服务器请求数据,减少不必要的数据请求,减少数据在浏览器和服务器间不必要的来回传递。

可以长期存储数据,无时间限制,一天、一年、甚至更长,都可以使用。

一般浏览器支持5M大小,不同浏览器会有所的不同。

优点:

  • 拓宽了cookie的4K限制
  • 可以将第一次请求的5M大小数据直接存在本地,相比cookie节约带宽
  • localStorage的使用也遵循同源策略,不同的网站之间是不能公用相同的localStorage

缺点:

  • 需要手动删除,否则长期存在
  • 浏览器大小不一,版本的支持也不一样
  • localStorage只支持string类型的存储,JSON对象需要转换
  • localStorage本质上是对字符串的读取,存储内容多的话会消耗内存空间,页面变卡
4.4.3 sessionStorage

会话存储。

主要是前端开发人员,在前端设置,只有在浏览器被关闭之前使用,创建另一个页面时同时可以使用,关闭浏览器之后数据就会消失。

存储上限限制:不同得浏览器存储的上限也不一样,但大多数浏览器把上限限制在5M以下

4.4.4 websql

Web SQL是在浏览器上模拟数据库,可以使用js来操作SQL完成对数据的读写。它使用SQL来操纵客户端数据库的API,这些API是异步的,规范中使用的是SQLlite,数据库还是在服务端,不建议使用,已废弃

4.4.5 indexDB

随着浏览器的功能不断增强,越来越多的网站开始考虑将大量数据存储在客户端,以减少从服务器获取数据,直接从本地获取数据。

现有的浏览器数据存储方案,都不适合存储大量数据:Cookie大小不超过4kb,且每次请求都会发送回服务器;localStorage在2.5M到10M间,且不提供搜索功能,不能建立自定义索引。因此,需要一种新的解决方案,由此诞生了index DB。

indexDB就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。它允许存储大量数据,提供查找接口,还能建立索引。

它不属于关系型数据库(不支持SQL查询语句),更接近NoSQL数据库。

4.5 CDN内容分发网络

Content Delivery Network(Content Distribute Network)

客户端访问网站的过程

  • 没有CDN
    1. 用户在浏览器中输入要访问的域名
    2. 浏览器向DNS服务器请求对该域名的解析
    3. DNS服务器返回该域名的ip给浏览器
    4. 浏览器使用该IP地址向服务器请求内容
    5. 服务器将内容返回给浏览器
  • 使用了CDN
    1. 用户在浏览器中输入要访问的域名
    2. 浏览器向DNS服务器请求对域名进行解析。由于CDN对域名解析进行了调整,DNS服务器回最终将域名的解析权交给CNAME指向的CDN专用DNS服务器
    3. CDN的DNS服务器将CDN的负载均衡设备IP返回给用户
    4. 用户向CDN的负载均衡设备发起内容URL访问请求
    5. CDN负载均衡设备回为用户选择一台合适的缓存服务器提供服务。选择的依据包括:根据用户ip,判断哪一台服务器距离用户最近;根据用户请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器的负载情况,判断哪一台的服务器负载较小。综上分析后,负载均衡设备会把缓存服务器的IP返回给用户。
    6. 用户向缓存服务器发出请求
    7. 缓存服务器响应用户请求,将用户所需内容换送到用户。如果该台缓存服务器上没有用户想要的内容,而负载均衡设备依旧把它分配给了用户,那么该服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉取到本地。

附: DNS域名解析

  1. 用户向localDNS发起请求查询输入域名对应的IP地址(若有缓存直接返回,否则去rootDNS查询)
  2. localDNS迭代向rootDNS查询,逐级迭代,rootDNS=>顶级DNS=>次级DNS
  3. 获得次级DNS后,localDNS向次级DNS发起域名解析请求
  4. 次级DNS通常会将域名CNAME到另一个域名,这个域名最终会被指向CDN网络中的智能DNS负载均衡系统。
  5. DNS负载均衡系统通过一些智能算法,将最合适的CDN节点IP返回给localDNS
  6. localDNS将获得的IP返回给用户
  7. 用户得到节点的IP地址后,向该节点发起访问请求
  8. CDN节点返回请求文件,如果该节点中请求的文件不存在,就会再回到源站获取该文件,然后返回给用户。

DNS查询方式主要有递归和迭代。

递归是主机等待,其他DNS服务器进行询问。

迭代是DNS每次将结果给主机,让主机自己询问下一级DNS服务器。

递归就是:问问问问—答答答答。问的人一直在变化。

迭代就是:问答问答问答问答。问的人不变。

5. 浏览器同源策略与跨域

https://www.cnblogs.com/liwenzhou/p/9513648.html

5.1 基本理解同源策略

理解:

协议、域名、端口,任意一处有所不同的两个站点,在没有明确授权的情况下,都是不可以互相访问资源的。

(比如xyz.com下的js脚本用ajax读取abc.com里的文件数据是会被拒绝的。)

(注意,网站收到了请求并返回了响应,只是被浏览器拦截了!)

不受同源策略限制的特例:

  1. 页面中的链接、重定向以及表单提交,不会受到同源策略限制。
  2. 跨域资源的引入是可以的,但js不能读写加载的内容。比如嵌入到页面中的,,,等。

如:

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>

这个就可以用,而不会被拦截。

如果跨域发ajax请求,往往就会报一个经典错误:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://xxxx’ is therefore not allowed access.

5.2 解决跨域问题

5.2.1 JSONP

解决原理:利用上面第二种特例,即script标签引入不受限制来解决。

可以直接把src写成目标站点路径,动态写入来访问资源,可以是文件、可以是函数。其本质就是,创建一个回调函数,然后在远程服务上调用这个函数并且将JSON数据形式作为参数传递,完成回调。

具体实现细节等,可以通过javascript动态写入标签来实现。

jQuery中有专门的方法来实现jsonp。

getJSON方法。

<script>
  $("#b1").click(function () {
    $.getJSON("http://127.0.0.1:8002/abc/?callback=?", function (res) {
      console.log(res);
    })
  });
</script>

url后面必须带一个callback参数,这样getJSON方法才能知道是JSONP方式去访问服务。后面的?是jQuery内部自动生成的回调函数名。

如果想要自己指定回调函数名,或者服务规定了回调函数名的话,也可以用$.ajax方法来实现。

<script>
  $("#b1").click(function () {
    $.ajax({
      url: "http://127.0.0.1:8002/abc/",
      dataType: "jsonp",
      success: function (res) {
        console.log(res);
      }
    })
  })
</script>
5.2.2 CORS

跨域资源共享(cross-origin resource sharing)

它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而解决ajax只能同源使用的限制。

5.2.2.1 简介

它需要浏览器和服务器同时支持。目前主流的浏览器都支持CORS,所以只要后端服务支持CORS,就能够实现跨域。

5.2.2.2 简单请求和非简单请求

浏览器将CORS请求分成两类。

同时满足两大条件,则为简单请求:

  1. 请求方法是HEAD或GET或POST
  2. HTTP的头部信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限三个值application/x-www-form-urlencoded、multipart/form-data、text/plain。
  • 简单请求处理方式

在跨域场景下,浏览器发送简单请求时,会自动在请求头中添加表明请求来源的Origin字段。

表明该请求是从哪里发起的,服务端根据该字段的值判断是否允许该请求。

而后端程序只要在返回的响应头中加上Access-Control-Allow-Origin字段,并把该字段的值设置为跨域请求的来源地址,或简单的设置为*即可。

  • 非简单请求处理方式

用到的请求方法为PUT或DELETE,或者Content-Type字段类型是application/json的都是非简单请求。

对于非简单请求,浏览器会在请求之前发送一次OPTIONS预检请求,该请求会向后端服务询问:是否允许从当前源发送请求,并且询问允许的请求方法请求头字段

比如一个put请求后端不支持,浏览器报错。解决方法就是可以在后端,简单地给响应对象添加上常用请求方法(PUT、DELETE)的支持。

虽然能解决,但是这是不严谨的土方法。已经有人造好了轮子,比如django-cors-headers。

安装一下,然后进行配置即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值