同源策略是浏览器一个重要的安全策略,它用于限制一个 origin
的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介
同源的定义是两个 URL
的 协议、域名(子域名 + 主域名)、端口号 都相同,否则就会出现跨域
AJAX
请求不能发送API
访问: DOM
无法获得Cookie
LocalStorage
和 IndexDB
无法读取一般常说的跨域指网络跨域
CORS (跨源资源共享) 是 HTTP 的一部分,它允许浏览器向跨源服务器发出 XMLHttpRequest
请求,从而解决了 AJAX
只能同源使用的限制。
CORS
需要浏览器和服务器同时支持,目前所有浏览器均已支持,只需服务器配置即可使用
浏览器将 CORS
请求分成两类: 简单请求和非简单请求
日常开发只会关注前两点
HEAD
GET
POST
Accept
Accept-Language
Content-Language
Content-Type
仅限以下三种
application/x-www-form-urlencoded
multipart/form-data
text/plain
XMLHttpRequestUpload
对象均没有注册任何事件监听器(使用 XMLHttpRequest.upload
属性访问XMLHttpRequestUpload
对象)ReadableStream
对象CORS
请求并在请求头信息之中增加一个 Origin
字段(用来说明本次请求来自哪个源(协议 + 域名 + 端口))Origin
字段决定是否同意这次请求CORS
相关的字段(以Access-Control-
开头)CORS
相关的字段,浏览器会抛出异常Access-Control-Allow-Origin
: 只能是 *
(接受任意域名的请求)或者是请求时 Origin
字段的值Access-Control-Allow-Credentials
(可选): 是一个布尔值,表示是否允许发送 Cookie
Access-Control-Expose-Headers
(可选): CORS
请求时 XMLHttpRequest
对象的 getResponseHeader()
方法只能拿到 6 个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
。如果想拿到其他字段就必须在 Access-Control-Expose-Headers
里面指定CORS
请求默认不发送 Cookie
,如果需要发送需要满足如下条件
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin
字段不能为 *
AJAX
请求的配置项需设置 withCredentials = true
非简单请求是那种对服务器有特殊要求的请求,如请求方法是 PUT
或 DELETE
,或者 Content-Type
字段的类型是 application/json
。 非简单请求会在正式通信之前增加一次 HTTP
查询请求,称为预检请求,用于获取服务器是否允许该实际请求,同时避免跨域请求对服务器的用户数据产生预期之外的影响
预检请求用的请求方法是 OPTIONS
表示这个请求是用来询问的
Origin
: 表示本次请求来自哪个源Access-Control-Request-Method
: 用于列出浏览器的 CORS
请求会用到哪些 HTTP
方法Access-Control-Request-Headers
(可选): 指定浏览器 CORS
请求会额外发送的头信息字段Access-Control-Allow-Origin
Access-Control-Allow-Credentials
(可选)Access-Control-Allow-Methods
: 表示服务器支持的所有跨域请求的方法(为了避免多次预检请求)Access-Control-Allow-Headers
: 表示服务器支持的所有头信息字段,不限于浏览器在预检中请求的字段Access-Control-Max-Age
(可选): 用来指定本次预检请求的有效期单位为秒,在有效期内将不发出另一条预检请求一旦服务器通过了预检请求,以后每次浏览器正常的 CORS
请求,就都跟简单请求一样会有一个 Origin
头信息字段。服务器的回应也都会有一个 Access-Control-Allow-Origin
头信息字段
JSONP
是利用 <script>
标签没有跨域限制的漏洞,当前源可以得到从其他来源动态产生的 JSON
数据
JSONP
请求过程流程
script
标签,其 src
指向接口地址并拼接好参数和回调函数名JavaScript
脚本 )JavaScript
脚本代码(调用定义好的回调函数)并删除刚创建的 script
标签GET
请求XSS
攻击Expires
是服务器告诉浏览器的缓存过期时间(值为 GMT
时间,即格林尼治时间)
HTTP1.0
的产物max-age=xxx
(xxx 是 秒)Cache-Control
用于控制缓存的行为
HTTP1.1
的产物public
:允许被客户端和代理服务器缓存private
:只允许被客户端缓存(默认值)no-cache
:允许被客户端和代理服务器缓存,但在使用缓存时需要经过协商缓存来验证决定no-store
:所有内容都不会被缓存,即不使用强制缓存也不使用协商缓存每次请求都会下载完整的资源maxage=xxx
:设置客户端和代理服务器的缓存时间,表示缓存内容将在 xxx 秒后失效s-maxage=xxx
:设置代理服务器的缓存时间(优先级比 max-age
高)no-cache
名字存在误导,其并不是不缓存数据,只是在使用缓存时需要经过协商缓存来验证决定 max-age=0
和 no-cache
效果一致
JS
和图片文件会存入内存200(from memory cache)
I/O
操作memory cache
慢css
200(from disk cache)
HTTPS
下可用、存在兼容问题200(from service worker)
Last-Modified
和 If-Modified-Since
Last-Modified
表示资源的最后修改时间,值为 GMT
格式时间字符串,精确到秒
Last-Modified
If-Modified-Since
值为上次请求返回的 Last-Modified
If-Modified-Since
和该资源在服务器的最后被修改时间做对比
If-Modified-Since
重新返回资源文件,状态码为 200If-Modified-Since
资源无更新继续使用缓存文件,状态码为 304ETag
是服务器通过算法对资源内容计算出的一个唯一标识(文件 hash
)其有强弱之分
Etag
ETag: "<etag_value>"
Etag
(使用 W/
标识)
ETag: W/"<etag_value>"
ETag
If-None-Match
值为上次请求返回的 ETag
ETag
和服务器重新生成的 ETag
进行对比
Etag
优于 Last-Modified
Etag < Last-Modified
每次生成 ETag
都需要进行读写操作,而 Last-Modified
只需要读取操作Etag
强缓存 | 协商缓存 |
---|---|
不常变化的文件带 hash 值的 css js 图片 | 频繁变动的文件html 文件 |
disk cache
(磁盘缓存)中是否有匹配,有则使用缓存,没有则发送网络请求tab
标签并没有关闭,因此 memory cache
(内存缓存)是可用的,会被优先使用,其次使用 disk cache
(磁盘缓存)Cache-control: no-cache
(为了兼容还带了 Pragma: no-cache
)服务器直接返回 200 和最新内容。Cookie
(也叫 Web Cookie
或浏览器 Cookie
)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie
使基于无状态的 HTTP
协议记录稳定的状态信息成为了可能,Cookie
在存储时是以键值对的形式存在的
Cookie
主要用于以下三个方面:
Cookie
的本职工作并非本地存储,而是“维持状态”,因当时并没有其它合适的存储办法而作为唯一的存储手段,所以会用其进行本地存储
http response header
中的 set-cookie
JavaScript
中使用 document.cookie
进行读写Cookie
最大只能有 4KB
同时大多数浏览器对一个站点的 Cookie
个数也是有限制的Cookie
从而带来不必要的开销和安全问题Web Storage是 HTML5
专门为浏览器存储而提供的数据存储机制,其大小限制为 5MB ~ 10MB
(去查看当前浏览器下 Web Storage 的容量限制),数据仅保存在客户端不与服务器进行通信
Web Storage
提供了两种机制供我们使用
Local Storage
(本地存储)Session Storage
(会话存储)SessionStorage
数据SessionStorage
数据是独立的,不会相互影响(类似深拷贝)以
localStorage
为例
Cookie
: 可以设置失效时间(默认是关闭浏览器后失效)localStorage
: 除非被手动清除否则将会永久保存sessionStorage
: 仅在当前浏览器的标签页下有效,关闭标签或窗口后就会被清除Cookie
: 4KBlocalStorage
和 sessionStorage
: 5MB ~ 10MB
Cookie
: 每次都会携带在 HTTP
请求头中localStorage
和 sessionStorage
: 仅在客户储保存不会与服务器通信IndexedDB 是一个运行在浏览器上的非关系型数据库,用于在客户端存储大量结构化数据
250MB
甚至没有上限)ArrayBuffer
和 Blob
)打开/创建一个 IndexedDB 数据库,并指定数据库的版本号 (版本号只能为整数)
创建一个对象仓库(类似于数据库中的表)
添加数据
获取数据
修改数据
删除数据
name:value
的简单语法的客户端数据存储垫片,基于 IndexedDB
实现,并在不持支 IndexedDB
的浏览器中自动回退到 WebSQL
和 localStorage
IndexedDB
的封装,通过提供更友好和简单语法进行快速的编码开发IndexedDB
的封装,通过提供更友好和简单语法进行快速的编码开发