JS中的——跨域CORS

1,167 阅读5分钟

js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

例如:www.abc.com/index.html 请求 www.efg.com/service.php…

有一点必须要注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。

image.png

特别说明两点:

第一:如果是协议和端口造成的跨域问题“前台”是无能为力的。

第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”
可以理解为“协议, 域名和端口必须匹配”。

二、什么是同源策略及其限制

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。它的存在可以保护用户隐私信息,防止身份伪造等(读取Cookie)。

同源策略限制内容有:

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求不能发送

但是有三个标签是允许跨域加载资源:

image.png

接下来我们讨论下有哪些处理跨域的方法。但所有的跨域都必须经过信息提供方的允许。如果未经允许即可获取,那是浏览器同源策略出现漏洞。

CORS 跨域资源共享

简介

  • CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。是目前主流的跨域解决方案。

  • CORS需要浏览器和服务器同时支持。目前,所有现代浏览器都支持该功能(IE浏览器不能低于IE10。IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

  • 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

两种请求

  • 简单请求
  • 非简单请求

浏览器对这两种请求方式的处理方式是不同的。

只要满足下面条件就是简单请求:

  • 请求方法是三种方法之一:

1、HEAD 2、POST 3、GET

  • http头信息不超出一下字段:

1、Accept
2、Accept-Language
3、Content-Language
4、Last-Event-ID
5、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回调函数捕获。

如果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。默认情况下是false,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器(此时Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名)。
  • Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
当浏览器进行跨域请求的时候,会在请求里添加头部origin,表明自己协议,主机,端口。当服务器收到这个客户端发送的请求之后,如果需要允许能够访问,就需要添加头部信息Access-Control-Arrow-Origin到响应里面。浏览器收到传回来的这个头部信息就知道能不能进行跨域请求了。

const router=require("./router.js")
router.get("/ajax1",function(req,res){
    res.end('{"title":"jack"}')
})

router.get("/ajax2",function(req,res){
    res.setHeader("Access-Control-Allow-Origin","*")
    res.end('{"info":"hello","age":20,"name":"karen"}')
})