什么是 CORS 跨域访问?
CORS(Cross-Origin Resource Sharing)是指跨域资源共享,在前端开发中经常会遇到的问题。简单来说,现代浏览器为了保护用户的浏览器安全,限制了浏览器从一个域名下发送 XMLHttpRequest 的请求时间。
举个例子:我们有个域名为 www.example.com
,如果想从这个域名下的 HTML 页面通过 Ajax 请求获取另一个域名,比如 www.example.org
的数据,就会面对浏览器的阻拦。
解决方案
JSONP
在早期的前端开发中,为了解决跨域问题,存在一种叫做 JSONP(JSON with Padding)的技术。这种技术主要利用了 <script>
标签可以跨域的特性,将请求将转化成类似于动态创建一个 script
的方式进行加载。
但是,JSONP 只适用于 GET 请求,而且只能够支持 HTTP 的一些简单的操作。所以,现在我们通常使用的解决方案是 CORS。
CORS
CORS 技术需要依赖服务器端的配置。我们需要让服务器端允许跨域。
简单请求
简单请求是指满足下列需求之一的请求:
- 请求方法为 GET、HEAD 或者 POST。
- HTTP头信息不超过以下几种格式(区分大小写):
- Accept
- Accept-Language
- Content-Language
- Content-Type (只限于
application/x-www-form-urlencoded
、multipart/form-data
和text/plain
)
如果满足上述条件,那么浏览器将会多下发一个 OPTIONS 请求,用来获取服务器端的允许信息,再发起正式的请求。
在服务器端,只需要加入返回头信息 Access-Control-Allow-Origin,允许指定域名进行跨域访问就可以了。例如:
Access-Control-Allow-Origin: *
如果你想让访问来源都经过验证,可以这样做:
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
如果你只想允许某个域名进行访问,可以这样写:
Access-Control-Allow-Origin: http:// specificdomain.com
这里需要指出的是,针对 cookies,我们还需要指定 withCredentials
字段为 true,并且在服务器端的返回头信息需要加入 Access-Control-Allow-Credentials: true
。
非简单请求
如果简单请求的条件都不满足,就需要使用非简单请求的方法。非简单请求时浏览器的预检请求机制,同样需要服务器端进行配置。
具体的做法是服务器端需要在响应中加入以下响应头信息:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
这样的是为了告诉浏览器,本站支持的请求方法。同时我们需要在响应头信息的 Access-Control-Allow-Headers
字段进行设置,这样,浏览器才会响应 POST 请求。
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
如果想要支持 cookies,则必须在响应头信息中加入下面这个字段:
Access-Control-Allow-Credentials: true
总结
以上就是跨域访问的基本介绍了,CORS 技术可以解决前端开发中,很多时候需要进行跨域访问的问题,不过需要注意的是,每次请求都会带上 Origin 字段,包含了请求来源的信息。简单请求需要加上 Access-Control-Allow-Origin
表明访问来源。尤其注意,如果针对 cookies,我们还需要指定 withCredentials
为 true。
示例代码
以下是一个简单请求的实例代码:
var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.responseText); } }; xhr.open('GET', 'http://domain-b.com/resource', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(); // 响应头信息 Access-Control-Allow-Origin: *
以下是一个非简单请求的实例代码:
var preflightXHR = new XMLHttpRequest(); preflightXHR.open('OPTIONS', 'http://domain-b.com/resource', true); preflightXHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); preflightXHR.setRequestHeader('X-Custom-Header', 'valueone'); preflightXHR.onreadystatechange = function() { if (preflightXHR.readyState === 4 && preflightXHR.status === 200) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.responseText); } }; xhr.open('POST', 'http://domain-b.com/resource', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader('X-Custom-Header', 'valueone'); xhr.send('a=1&b=2'); // 响应头信息 Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept Access-Control-Allow-Credentials: true } }; preflightXHR.send(); // 响应头信息 Access-Control-Allow-Origin: http:// http://domain-a.com
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b230bcadd4f0e0ffb5e256