前端跨域解决方案

文章目录

    • 注意,本文已迁移
  • 1.同源政策
  • 2.跨域解决方案
    • 2.1 CORS
      • 普通跨域请求:只需服务端设置Access-Control-Allow-Origin即可
      • 携带cookie跨域请求:前后端都需设置
    • 2.2 postMessage跨域
    • 2.3 JSONP
      • 原理
      • 缺点
      • 数据格式
      • jsonp跨域实现
    • 2.4 WebSocket
        • 属性:
        • 事件:
    • 2.5 代理跨域:开启一个代理服务器实现数据转发
    • 2.6 iframe系列

注意,本文已迁移

本文具体内容已迁移到新网页,请读者移步查看,后续所有文章更新也将在新网站:
前端跨域解决方案

1.同源政策

  1. 如果两个页面拥有相同的协议、域名和端口,那么这两个页面就属于同一个源,其中只要有一个不相同,就是不同源。
    http://www.example.com:8080/dir/page.html
    http://www.example.com/page.html不跨域
    http:协议
    www:子域名
    example:主域名
    8080:端口号(http默认8080)

  2. 同源策略的限制:
    Cookie、LocalStorage 和 IndexDB 无法读取
    AJAX 请求不能发送

  3. 跨域是浏览器为了安全而实施的同源政策导致的

2.跨域解决方案

跨域报错:在这里插入图片描述

2.1 CORS

有几个关键的响应头字段:

a、Access-Control-Allow-Origin:必填,表示可以允许请求的来源。可以填写具体的源名称,也可以填写*表示允许任何源请求。

b、Access-Control-Allow-Methods:表示允许的请求方法列表。

c、Access-Control-Allow-Credentials:一个布尔值,表示是否允许发送cookie。默认情况下,cookie 不包含在 CORS 请求中。如果设置为 true,则表示服务器具有显式权限。Cookies 可以包含在请求中并一起发送到服务器。

d、Access-Control-Allow-Headers:其指明了实际请求中允许携带的首部字段。CORS请求时,XMLHttpRequest对象的getresponseheader()方法只能获取六个基本字段:缓存控制、内容语言、内容类型、过期时间、最后修改时间和pragma。如果要获取其他字段,则必须在访问控制公开标头中指定它们。

e、Access-Control-Max-Age:预检请求的有效期。在此期间,无需再次发送预检请求。

普通跨域请求:只需服务端设置Access-Control-Allow-Origin即可

Access-Control-Allow-Origin: *表示该资源可以被任意外域访问,若设置具体的值则只可与设置的值跨域

备注: 当响应的是附带身份凭证的请求时( cookie ),服务端 必须 明确 Access-Control-Allow-Origin 的值,而不能使用通配符“*”。

携带cookie跨域请求:前后端都需设置

如果设置 Access-Control-Allow-Origin: * ,不管withCredentials有没有设置,cookie也不会携带

前端设置:
若使用原生ajax

//使用ajax时加上withCredentials属性为true以携带cookie
xhr.withCredentials = true;

若用jQuery ajax

$.ajax({
   url:'',
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
});

服务器端设置:

// 允许跨域访问的域名:若有端口需写全,注意不能用*
"Access-Control-Allow-Origin""http://www.domain1.com" 

// 允许前端带认证cookie
"Access-Control-Allow-Credentials""true"

2.2 postMessage跨域

语法:otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow: 其他窗口的一个引用,比如 iframe 的 contentWindow 属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames
message:将要发送到其他 window的数据
targetOrigin:指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI(最好填一个确切的url)。
transfer (可选):是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权

接收其他域传来的数据:
window.addEventListener("message", function(e){ console.log(e.data) },false);

message 的属性有:
data:从其他 window 中传递过来的数据对象。
origin:调用 postMessage 时消息发送方窗口的 origin . 例如 “https://example.org (隐含端口 443)”。请注意,这个origin不能保证是该窗口的当前或未来origin,因为postMessage被调用后可能被导航到不同的位置。
source:对发送消息的窗口对象的引用; 您可以使用此来在具有不同origin的两个窗口之间建立双向通信。

2.3 JSONP

原理

JSONP主要就是利用了script标签没有跨域限制的这个特性来完成的,它可以通过src填写目标地址,发送一个带回调参数的get请求。服务器将接口返回数据分割成回调函数返回给浏览器。浏览器解析并执行就可得到服务器返回的数据。

缺点

只支持get请求,不支持post请求。适用于加载不同域名的js、css、img等静态资源

数据格式

键值对,要加双引号,除了值为数字时不用加双引号

[
  {
    "id":1,
    "name":"Rick",
    "email":"[email protected]"
  },
  {
    "id":2,
    "name":"Glenn",
    "email":"[email protected]"
  }
]

jsonp跨域实现

2.4 WebSocket

WebSocket 对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。
使用 WebSocket() 构造函数来构造一个 WebSocket

var aWebSocket = new WebSocket(url [, protocols]);
url:要连接的URL;WebSocket服务器将响应的URL。
protocols 可选:一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议(例如,您可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互)。如果不指定协议字符串,则假定为空字符串。

属性:

WebSocket.onclose 用于指定连接关闭后的回调函数。
WebSocket.onerror 用于指定连接失败后的回调函数。
WebSocket.onmessage 用于指定当从服务器接受到信息时的回调函数。
WebSocket.onopen 用于指定连接成功后的回调函数。
WebSocket.url (只读) WebSocket 的绝对路径。

事件:

2.5 代理跨域:开启一个代理服务器实现数据转发

前端跨域解决方案_第1张图片 前端跨域解决方案_第2张图片

2.6 iframe系列

document.domain +iframe跨域:两个页面都通过js强制设置document domain为基础主域,实现同域
locatin.hash + iframe跨域: a 与b跨域相互通信,通过中间页c来实现,三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
window. name + iframe跨域:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。
详见:https://segmentfault.com/a/1190000022398875

你可能感兴趣的:(前端,javascript,http)