同源和跨域
同源与跨域
- 源
- window.orgin 或者 location.origin 可以得到当前源
- 源 = 协议 + 域名 + 端口
- 同源
- 协议相同
- 域名相同
- 端口号相同
- 同源限制
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB。
- 无法接触非同源网页的 DOM。
- 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)。
- 跨域
- 明确了同源限制之后,就能明白跨域其实就是突破同源限制向非非同源服务器请求数据
JSONP 方法实现跨域
JSONP 即 JSON WITH PADDING,特点是简单易用,服务器端改造小,没有兼容问题,IE 可以使用。
它的做法如下。
第一步,网页添加一个 <script>
元素,向服务器请求一个脚本,这不受同源政策限制,可以跨域请求。
1 |
|
注意,请求的脚本网址有一个 callback 参数(?callback=bar),用来告诉服务器,客户端的回调函数名称(bar)。
第二步,服务器收到请求后,拼接一个字符串,将 JSON 数据放在函数名里面,作为字符串返回(bar({…}))。
第三步,客户端会将服务器返回的字符串,作为代码解析,因为浏览器认为,这是 <script>
标签请求的脚本内容。这时,客户端只要定义了 bar() 函数,就能在该函数体内,拿到服务器返回的 JSON 数据。
下面看一个实例。首先,网页动态插入 <script>
元素,由它向跨域网址发出请求。
1 |
|
上面代码通过动态添加 <script>
元素,向服务器 example.com 发出请求。注意,该请求的查询字符串有一个 callback 参数,用来指定回调函数的名字,这对于 JSONP 是必需的。
服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。
1 |
|
由于 <script>
元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了 foo 函数,该函数就会立即调用。作为参数的 JSON 数据被视为 JavaScript 对象,而不是字符串,因此避免了使用 JSON.parse 的步骤。
CORS 实现跨域
CORS 即“跨域资源共享”(Cross-origin resource sharing),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
- 请求方法:
对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是浏览器自动在头信息之中,增加一个 Origin 字段,如果 Origin 指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
1 |
|
上面的头信息之中,有三个与 CORS 请求相关的字段,都以Access-Control-
开头。
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin
字段的值,要么是一个*
,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中。设为true
,即表示服务器明确许可,浏览器可以把 Cookie 包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送 Cookie,不发送该字段即可。
(3)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
字段的值。
对于复杂请求,则需要在响应端添加其他的的响应头:
响应 OPTIONS 请求,在响应中添加如下的响应头
1
2
3Access-Control-Allow-Origin: https://甲站点
Access-Control- Allow-Methods: POST, GET, OPTIONS, PATCH
Access-Control-Allow- Headers: Content-Type响应 POST 请求,在响应中添加
Access-Control-Allow-Origin
头。
如果需要附带身份信息,JS 中需要在 AJAX 里设置
xhr.withCredentials=true
。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!