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的恶意篡改利用。
攻击方式:
- 盗用cookie(比如document.cookie),获取敏感信息
- 利用植入Flash,通过crossdomain权限设置进一步获取更高权限
- 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击者)用户的身份执行一些管理操作,或执行一些一般的比如发微博、加好友、发私信等操作。
- 利用可被攻击的域受到其他域信任这一特点,以受信任来源的身份请求一些平时不允许的操作,比如进行不当的投票活动。
- 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。
1.2 心得体会
本质:
-
恶意代码未经过滤,和正常代码混在一起,浏览器都给执行了。
-
又由于直接在用户的终端执行,所以能直接获取用户信息,然后利用这些信息冒充用户向网站发起攻击者定义的请求。
-
在部分情况下由于输入的限制,注入的恶意脚本一般比较短。但可以通过引入外部脚本并由浏览器执行,来完成比较复杂的攻击策略。
持久化:
因为脚本直接被保存到了服务器(数据库)上,所以,所有用户浏览时都会读取到该恶意脚本,进而执行。
2. CSRF
Cross-site request forgery
跨站请求伪造
https://www.freebuf.com/articles/web/118352.html
核心本质:利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。它与XSS区别在于,它没有盗取cookie,而是直接利用,“冒充用户”
一个攻击过程
- 受害者登录a.com,保留了登录凭证(Cookie)
- 攻击者引诱受害者访问了b.com
- b.com向a.com发送了一个请求,a.com/act=xx。浏览器会默认携带a.com的cookie。
- a.com收到请求后,对请求进行验证,确认是受害者的凭证,误以为是受害者自己发送的请求。
- a.com以受害者的名义执行了act=xx
- 攻击完成。攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了攻击者定义的操作。
CSRF防护策略
大多来自第三方网站,就直接禁止外域(不受信任的域名)对我们发起请求。
在部分与CSRF有关的请求中,请求的header中会携带Origin字段。字段内包含请求的域名(不包含path及query)。如果Origin存在,那么直接使用Origin中的字段来确认来源域名即可。
CSRF token
它之所以能够攻击成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带了正确的Token,来把正常的请求和攻击的请求区分开。
- 首先,用户打开页面,服务器给该用户生成一个Token。每次页面加载时,用JS遍历整个DOM树,对DOM中所有的a和form标签后面加入Token。
- 页面提交的请求携带这个Token
- 服务端验证Token是否有效。当用户从客户端得到了Token,再次提交给服务器时,服务器判断Token的有效性。验证过程时先解密Token,对比加密字符串以及时间戳,如果加密字符串一致且事件没过期,则该Token有效。
3. 浏览器
参考:
https://kb.cnblogs.com/page/129756/
3.1 浏览器主要功能
将用户选择的web资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中。资源格式通常为HTML,也包括pdf、image等其他格式。
3.2 主要构成
- 用户界面
包括地址栏、后退、前进按钮、书签目录等。即我们所能看到的,除了用来显示我们所请求页面的主窗口之外的其他部分。
- 浏览器引擎
用来查询及操作渲染引擎的接口。
- 渲染引擎
用来显示请求的内容。例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来。
- 网络
用于完成网络调用。比如http请求,它具有平台无关的接口,可在不同平台上工作。
- UI后端
用于绘制类似组合选择框及对话框等基本组件,句有不特定于某个平台的通用接口,底层使用操作系统的用户接口。
- JS解释器
用于解释执行JS代码
- 数据存储
属于持久层。浏览器需要在硬盘中保存类似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分块的方式完成。
获取内容之后才进入基本流程:
-
解析html以构建DOM树
-
构建render树
-
布局render树
-
绘制render树
-
渲染引擎解析html,将标签转化为内容树中的dom节点。紧接着,解析外部css文件以及style标签中的样式信息。这些样式信息以及html终得可见性指令将被用来构建另一棵树——render树。
-
render树由一些包含有颜色和大小等属性的矩形组成,它们将被按照正确顺序显示到屏幕上。
-
render树构建完毕后,会执行布局过程,它将确定每个节点在屏幕上的确切坐标。
-
然后绘制,即遍历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通知客户端直接用本地缓存即可。
- 两种协商缓存对比
- 在精确度上,ETag优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1s内修改了很多次,那么其Last-Modified其实并没有体现出修改,但是ETag每次都会改变,保证了精度。如果是负载均衡的服务器,各个服务器生成的Last-Modified也可能不一致。
- 性能上,Etag逊于Last-Modified。因为后者只需要记录时间,而前者需要服务器通过算法来计算一个hash值。
- 优先级上,服务器校验优先考虑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
- 用户在浏览器中输入要访问的域名
- 浏览器向DNS服务器请求对该域名的解析
- DNS服务器返回该域名的ip给浏览器
- 浏览器使用该IP地址向服务器请求内容
- 服务器将内容返回给浏览器
- 使用了CDN
- 用户在浏览器中输入要访问的域名
- 浏览器向DNS服务器请求对域名进行解析。由于CDN对域名解析进行了调整,DNS服务器回最终将域名的解析权交给CNAME指向的CDN专用DNS服务器
- CDN的DNS服务器将CDN的负载均衡设备IP返回给用户
- 用户向CDN的负载均衡设备发起内容URL访问请求
- CDN负载均衡设备回为用户选择一台合适的缓存服务器提供服务。选择的依据包括:根据用户ip,判断哪一台服务器距离用户最近;根据用户请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器的负载情况,判断哪一台的服务器负载较小。综上分析后,负载均衡设备会把缓存服务器的IP返回给用户。
- 用户向缓存服务器发出请求
- 缓存服务器响应用户请求,将用户所需内容换送到用户。如果该台缓存服务器上没有用户想要的内容,而负载均衡设备依旧把它分配给了用户,那么该服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉取到本地。
附: DNS域名解析
- 用户向localDNS发起请求查询输入域名对应的IP地址(若有缓存直接返回,否则去rootDNS查询)
- localDNS迭代向rootDNS查询,逐级迭代,rootDNS=>顶级DNS=>次级DNS
- 获得次级DNS后,localDNS向次级DNS发起域名解析请求
- 次级DNS通常会将域名CNAME到另一个域名,这个域名最终会被指向CDN网络中的智能DNS负载均衡系统。
- DNS负载均衡系统通过一些智能算法,将最合适的CDN节点IP返回给localDNS
- localDNS将获得的IP返回给用户
- 用户得到节点的IP地址后,向该节点发起访问请求
- CDN节点返回请求文件,如果该节点中请求的文件不存在,就会再回到源站获取该文件,然后返回给用户。
DNS查询方式主要有递归和迭代。
递归是主机等待,其他DNS服务器进行询问。
迭代是DNS每次将结果给主机,让主机自己询问下一级DNS服务器。
递归就是:问问问问—答答答答。问的人一直在变化。
迭代就是:问答问答问答问答。问的人不变。
5. 浏览器同源策略与跨域
https://www.cnblogs.com/liwenzhou/p/9513648.html
5.1 基本理解同源策略
理解:
协议、域名、端口,任意一处有所不同的两个站点,在没有明确授权的情况下,都是不可以互相访问资源的。
(比如xyz.com下的js脚本用ajax读取abc.com里的文件数据是会被拒绝的。)
(注意,网站收到了请求并返回了响应,只是被浏览器拦截了!)
不受同源策略限制的特例:
- 页面中的链接、重定向以及表单提交,不会受到同源策略限制。
- 跨域资源的引入是可以的,但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请求分成两类。
同时满足两大条件,则为简单请求:
- 请求方法是HEAD或GET或POST
- 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。
安装一下,然后进行配置即可。