跨域问题--cors解决方案
一、 跨域
js出于安全方面的考虑,不允许不同域调用其他页面的对象。当协议、域名、端口号任意一个不相同时,就算不同域。
跨域并不是请求发不出去,而是请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。
二、跨域解决
1. jsonp
jsonp优点就是可以兼容各种浏览器,而缺点也很明显,只能发送get请求。
jsonp利用了script标签加载机制,它发送的不是ajax请求。
客户端代码:
1 | function getData() { |
服务端代码:
1 | const express = require('express') |
2. cors跨域解决方案
CORS:跨源资源共享,基于http协议,通过允许服务器标示除了它自己以外的其它origin来实现请求。
CORS需要浏览器和服务器同时支持,IE不低于IE10。
cors的两种请求
CORS请求分为两类:简单请求和预检请求。
符合下面条件的就是简单请求:
请求方式使用下列方法之一:
GET
HEAD
POSTContent-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。同样,在响应头中,返回服务器设置的相关CORS头部字段,Access-Control-Allow-Origin字段为允许跨域请求的源。
预检请求:
使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCHContent-Type 的值不属于下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
当发生符合非简单请求(预检请求)的条件时,浏览器会自动先发送一个options请求,如果发现服务器支持该请求,则会将真正的请求发送到后端,反之,如果浏览器发现服务端并不支持该请求,则会在控制台抛出错误
如果非简单请求(预检请求)发送成功,则会在头部多返回以下字段:
Access-Control-Allow-Origin: http://localhost:3001 //该字段表明可供那个源跨域
Access-Control-Allow-Methods: GET, POST, PUT // 该字段表明服务端支持的请求方法
Access-Control-Allow-Headers: X-Custom-Header // 实际请求将携带的自定义请求首部字段
实例代码:
1 | const express = require('express') |
注意:
需要携带cookie信息时,需要将Access-Control-Allow-Credentials设置为true,同时axios也需要打开:xhr.withCredentials=true