前言:随着工作时间的增长,前面学过的东西开始慢慢遗忘,抽空的时候就将一些资料整理整理,顺一顺,也当作一种温习。我只是前端工匠,防止自己成为【一断网就无法工作的程序员】
url 的完整结构
协议类型(protocol)
通过 URL 可以指定的主要有以下几种:http、ftp、gopher、telnet、file 等
URL 的组成协议 1、protocol(协议):指定使用的传输协议,下表列出 protocol 属性的有效方案名称。
最常用的是 HTTP 协议,它也是目前 WWW 中应用最广的协议。
http —— 超文本传输协议访问该资源。格式 http://
https —— 用安全套接字层传送的超文本传输协议访问该资源。格式 https://
ftp —— 通过 FTP 访问资源。格式 FTP://
mailto —— 电子邮件地址 通过 SMTP 访问。格式 mailto:
ldap —— 轻型目录访问协议搜索
file —— 资源是本地计算机上的文件。格式 file://
news —— Usenet 新闻组
gopher —— Gopher 协议
telnet —— Telnet 协议
主机名(hostname)
是指存放资源的服务器的域名系统 (DNS) 主机名或 IP 地址。
有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password)。
端口号(port)
整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,
如 http 的默认端口为 80,https 的默认端口为 443
路径及文件名(path)
由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
参数(parameters)
传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开
hash 值
#是用来指导浏览器动作的,对服务器端完全无用。所以,HTTP 请求中不包括 #。
这些字符都不会被发送到服务器端。
改变 #不触发网页重载
改变 #会改变浏览器的访问历史
默认情况下,Google 的网络蜘蛛忽视 URL 的 #部分。
但是,Google 还规定,如果你希望 Ajax 生成的内容被浏览引擎读取,
那么 URL 中可以使用 ”#!”,Google 会自动将其后面的内容转成查询字符串_escaped_fragment_的值
同源策略
协议相同
域名相同
端口相同
如果非同源,共有三种行为收到限制
(1)Cookie、LocalStorage 和 IndexDB 无法读取。
(2)DOM 无法获得。
(3)AJAX 请求不能发送。
Cookie
Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。
cookie 的组成部分
Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE
NAME=VALUE
NAME 是该 Cookie 的名称,VALUE 是该 Cookie 的值。
在字符串“NAME=VALUE”中,不含分号、逗号和空格等字符。
Expires=DATE:Expires 变量是一个只写变量,它确定了 Cookie 有效终止日期。
该属性值 DATE 必须以特定的格式来书写:星期几,DD-MM-YY HH:MM:SS GMT,
GMT 表示这是格林尼治时间。
反之,不以这样的格式来书写,系统将无法识别。
该变量可省,如果缺省时,则 Cookie 的属性值不会保存在用户的硬盘中,
而仅仅保存在内存当中,Cookie 文件将随着浏览器的关闭而自动消失。
Domain=DOMAIN-NAME:Domain 该变量是一个只写变量,
它确定了哪些 Internet 域中的 Web 服务器可读取浏览器所存取的 Cookie,
即只有来自这个域的页面才可以使用 Cookie 中的信息。
这项设置是可选的,如果缺省时,设置 Cookie 的属性值为该 Web 服务器的域名。
Path=PATH:Path 属性定义了 Web 服务器上哪些路径下的页面可获取服务器设置的 Cookie。
一般如果用户输入的 URL 中的路径部分从第一个字符开始包含 Path 属性所定义的字符串,
浏览器就认为通过检查。如果 Path 属性的值为“/”,
则 Web 服务器上所有的 WWW 资源均可读取该 Cookie。
Secure:在 Cookie 中标记该变量,
表明只有当浏览器和 Web Server 之间的通信协议为加密认证协议时,
浏览器才向服务器提交相应的 Cookie。当前这种协议只有一种,即为 HTTPS。
cookie 在 Request Headers 中的传输格式
Cookie: KEY=VALUE; KEY=VALUE; KEY=VALUE
是没有 域 和 过期时间 的
跨域处理
两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置 document.domain 共享 Cookie。
document.domain = ‘example.com’;
如果两个网页不同源,就无法拿到对方的 DOM。
典型的例子是 iframe 窗口和 window.open 方法打开的窗口,它们与父窗口无法通信。
AJAX
除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),
vue 项目中 开发环境的跨域处理
proxyTable
dev: {
// Paths
assetsSubDirectory: ‘static’,
assetsPublicPath: ‘./’,
proxyTable: {
‘/api’: {
target: ‘http://temp.com’,// 请换成你需要跨域请求的地址
changeOrigin: true,
pathRewrite: {
‘^/api’: ”
}
}
}
}
proxyTable 中的 pathRewrite 的 /api 理解成用‘/api’代替 target 里面的地址,后面组件中我们掉接口时直接用 api 代替
有三种方法规避这个限制
JSONP
WebSocket
CORS
JSONP
是服务器与客户端跨源通信的常用方法。
最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
它的基本思想是,网页通过添加一个 <script> 元素,向服务器请求 JSON 数据,
这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
WebSocket
WebSocket 是一种通信协议,使用 ws://(非加密)和 wss://(加密)作为协议前缀。
该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
CORS
CORS 是跨源资源分享(Cross-Origin Resource Sharing)的缩写。
它是 W3C 标准,是跨源 AJAX 请求的根本解决方法。
相比 JSONP 只能发 GET 请求,CORS 允许任何类型的请求。
CORS 详解
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
两种请求
浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求
(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
凡是不同时满足上面两个条件,就属于非简单请求。
简单请求
对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个 Origin 字段。
下面是一个例子,浏览器发现这次跨源 AJAX 请求是简单请求,就自动在头信息之中,添加一个 Origin 字段。
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0…
上面的头信息中,Origin 字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果 Origin 指定的源,不在许可范围内,服务器会返回一个正常的 HTTP 回应。浏览器发现,这个回应的头信息没有包含 Access-Control-Allow-Origin 字段(详见下文),就知道出错了,从而抛出一个错误,被 XMLHttpRequest 的 onerror 回调函数捕获。注意,这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是 200。
如果 Origin 指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
上面的头信息之中,有三个与 CORS 请求相关的字段,都以 Access-Control- 开头。
Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时 Origin 字段的值,要么是一个 *,表示接受任意域名的请求。
Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中。设为 true,即表示服务器明确许可,Cookie 可以包含在请求中,一起发给服务器。这个值也只能设为 true,如果服务器不要浏览器发送 Cookie,删除该字段即可。
Access-Control-Expose-Headers 该字段可选。CORS 请求时,XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到 6 个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers 里面指定。上面的例子指定,getResponseHeader(‘FooBar’) 可以返回 FooBar 字段的值。
非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT 或 DELETE,或者 Content-Type 字段的类型是 application/json。
非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为 ” 预检 ” 请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
“ 预检 ” 请求用的请求方法是 OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是 Origin,表示请求来自哪个源。
除了 Origin 字段,” 预检 ” 请求的头信息包括两个特殊字段。
Access-Control-Request-Method 该字段是必须的,用来列出浏览器的 CORS 请求会用到哪些 HTTP 方法,上例是 PUT。
Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段,上例是 X -Custom-Header。
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0…
预检请求的回应
服务器收到 ” 预检 ” 请求以后,检查了 Origin、Access-Control-Request-Method 和 Access-Control-Request-Headers 字段以后,确认允许跨源请求,就可以做出回应。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
上面的 HTTP 回应中,关键的是 Access-Control-Allow-Origin 字段,
表示 http://api.bob.com 可以请求数据。该字段也可以设为星号,表示同意任意跨源请求。
关于更多的 cors 详情请查看阮一峰 跨域资源共享 CORS 详解