关于CORS跨域问题的理解

起因

因为这段时间一个项目前后端分别部署在不同服务器的需要,抽空学习了一下CORS问题,不足之处,欢迎指教.

什么是CORS

CORS是一个w3c标准,全称是"跨域资源共享"(Cross-origin resource sharing),但一个请求url的协议,域名,端口三者之间任意与当前页面地址不同即为跨域.它允许阅览器向跨源服务器发送XMLHttpRequest请求,从而客服AJAX只能同源使用的限制.

CORS简介

浏览器默认的安全限制为同源策略,即JavaScript或Cookie只能访问同源(相同协议,相同域名,相同端口)下的内容。但由于跨域访问资源需要,出现了CORS机制,这种机制让web服务器能跨站访问控制,使跨站数据传输更安全。CORS需要阅览器和服务器同时支持,目前,主流的阅览器都支持cors。

CORS的两种请求方式

浏览器将CORS请求分为两类:简单请求和非简单请求

一  简单请求

1.1 区分条件:

只要满足一下两大条件,属于简单请求:

(1) 请求方法是以下三种方法之一:
        HEAD
        GET
        POST
(2)HTTP的头信息不超出以下几种字段:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain        

不同时满足上面两个条件,就是非简单请求

1.2 简单请求的基本流程

浏览器直接发送CORS跨域请求,并在header信息中增加一个Origin字段,表明这是一个跨域的请求。

    <script>
        var url = ‘http://www.lishanlei.cn/CorsTest/CorsTest.php‘;
        var xhr = new XMLHttpRequest();
        xhr.open(‘get‘, url, true);
        // xhr.setRequestHeader(‘X-Custom-Header‘, ‘value‘);
        xhr.send();
    </script>

在上面的代码中以get形式向www.lishanlei.cn进行跨域访问。

上面的头信息Origin字段用来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,决定是否同意这次请求。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应,浏览器收到这个回应发现这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道错了,从而会抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意这种错误无法通过状态码识别,此时HTTP回应的状态码可能是200

如果Origin指定的域名在许可范围内,服务器返回的响应会多出几个头信息字段

Access-Control-Allow-Origin:该字段是必须的,其值可能是请求时Origin字段的值,也可能是一个*,表示接受任意域名请求。

Access-Control-Allow-Credentials:该字段可选,其值类型是布尔型,表示是否允许发送Cookie。默认情况下Cookie不包括在CORS请求中。当设为true时表示服务器明确许可,Cookie可以包含在请求中一起发送给服务器。

Access-Control-Allow-Headers:该字段必须,它是一个都好分割的字符串,表明服务器支持的所有头信息字段

1.3 withCredentials属性

默认情况下,CORS请求默认不发送Cookie和Http认证信息,如果要把Cookie发送到服务器,首先要指定Access-Control-Alloe-Credentials字段,另一方面,需要在AJAX请求中打开withCredentials属性

var xml = new XMLHttpRequest();
xml.withCredentials = true;

如果没有设置该属性为true,即使服务器统一发送Cookie,浏览器也不会发送。

当该属性设置为true时,即需要发送Cookie那么在服务器中Access-Control-Allow-Origin就不能设置成*,必须指定吗明确的与请求一致的域名,同时,Cookie依然遵循同源政策。

二  非简单请求

当不同时满足区分条件的,就是非简单请求。

2.1 预检请求

非简单请求的CORS请求,会在正式通信前进行一次Http查询请求,又称预检请求。

浏览器先请求服务器,当前网页所在域名是否在服务器许可名单中以及可以使用那些HTTP动词和头信息字段,当客户端得到肯定答复时,浏览器才会正式发出XMLHttpRequest请求。

var url = ‘http://www.lishanlei.cn/CorsTest/CorsTest.php‘;
var xhr = new XMLHttpRequest();
xhr.open(‘PUT‘, url, true);
xhr.setRequestHeader(‘X-Custom-Header‘, ‘value‘);
xhr.send();

上面代码中,请求方式是PUT,并发送一个自定义头信息X-custom-Header,但在服务器的头信息中没有包含X-custom-Header,故浏览器报错,只进行了一次预检请求。

设置header中的Access-Control-Allow-Headers字段:

header(‘Access-Control-Allow-Headers:x-requested-with,content-type,X-Custom-Header‘);

再次访问

浏览器发现这是一个非简单请求,自动发出一个预检请求,要求服务其确认这样的请求,下面是这个预检请求的HTTP头信息:

预检请求用的请求方法是OPTIONS,表示这个请求是用来询问的。

Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。

Access-Control-Request-Headers:该字段是一个逗号分割的字符串,指定浏览器CORS请求会额外发送的头信息字段。

2.2预检请求的回应

当服务其收到预检请求后,检查了Origin,Access-Control-Request-Method等信息字段后,如果没有问题,则确认允许跨源请求,就可以做出了回应。

Access-Control-Allow-Methods:该字段必须,其值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。这是为了避免多次预检请求。

Access-Control-Max-Age:该字段是可选的,用来指定本次预检请求的有效期,单位是秒。Access-Control-Max-Age:20,即允许缓存该条回应20秒,再此期间不用发出另一条预检请求

如果浏览器否定了预检请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。浏览器此时会认定服务器不同意预检请求,触发一个错误,被XMLHttpRequestonerror回调函数捕获。

服务器端处理机制

服务器对于跨域请求的处理流程如下:

  1. 首先查看http头部有无origin字段;
  2. 如果没有,或者不允许,当成普通请求;
  3. 如果有且是允许的,再看是否是preflight(method=OPTIONS);
  4. 如果不是preflight(简单请求),返回Allow-Origin,Allow-Credential等字段,并返回正常内容;
  5. 如果是preflight(非简单请求),返回Allow-Headers,Allow-Methods等;

配置CORS规则

一  apache上配置CORS规则

Apache需要使用mod_headers模块来激活HTTP头设置,默认是激活的,只需要修改Apache配置文件中的/etc/apache2/sites-available/000-default.conf

1 开启模块
sudo a2enmod headers
2 编辑配置文件
sudo vi /etc/apache2/sites-available/000-default.conf
3 在虚拟主机Directory设置下添加
Header set Access-Control-Allow-Origin *

与JSONP的比较

CORS和JSONP都是为了使web浏览器能够跨源请求,使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,而CORS支持所有类型的HTTP请求,不过JSONP的优势在于支持老式浏览器以及可以向不支持CORS的网站跨源请求。

参考博文http://www.ruanyifeng.com/blog/2016/04/cors.html

                 https://blog.csdn.net/u014344668/article/details/54948546

原文地址:https://www.cnblogs.com/lishanlei/p/8823823.html

时间: 2024-09-30 16:51:25

关于CORS跨域问题的理解的相关文章

jsonp与cors跨域的一些理解(转)

CORS其实出现时间不短了,它在维基百科上的定义是:跨域资源共享(CORS )是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源.而这种访问是被同源策略所禁止的.CORS系统定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求. 它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全. 而W3C的官方文档目前还是工作草案,但是正在朝着W3C推荐的方向前进. 简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的. 浏览器的同源策

jsonp与cors跨域的一些理解

浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作. 比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个网站的相关信息,很明显这是不安全的,所以同源策略避免了很多这样的问题. 但是同时也带来了一些问题,比如有时候你想通过自己的网站去获取另一个自己的网站的一些资料信息,但是由于两者域名不同,所以就被同源策略隔离了,那么这个时候就需要了解一下浏览器的跨域问题. 跨域常见的两种方式,分别是jsonp和新推出

CORS跨域资源共享你该知道的事儿

"唠嗑之前,一些客套话" CORS跨域资源共享,这个话题大家一定不陌生了,吃久了大转转公众号的深度技术好文,也该吃点儿小米粥溜溜胃里的缝儿了,今天咱们就再好好屡屡CORS跨域资源共享这个话题,大牛怡情小牛巩固,把这碗前端经久不凉的大碗茶,再细细的品一品. "JSONP直接了当很豪爽,CORS细吮慢品大补汤" 在咱们前端的日常工作中,跨域比较常用的方式就是JSONP,JSONP呢就是通过script标签无同源限制的特点,在获取到需要的资源后自动执行回调方法的方式,而我

CORS——跨域请求那些事儿

在日常的项目开发时会不可避免的需要进行跨域操作,而在实际进行跨域请求时,经常会遇到类似 No 'Access-Control-Allow-Origin' header is present on the requested resource.这样的报错.这样的错误,一般是由于CORS跨域验证机制设置不正确导致的,本文将详细讲解CORS跨域验证机制的原理,让您轻松掌握CORS跨域设置的使用方法,安全.方便的进行前端开发. 什么是CORS CORS(Cross-Origin Resource Sha

解决ajax请求cors跨域问题

”已阻止跨源请求:同源策略禁止读取位于 ***** 的远程资源.(原因:CORS 头缺少 'Access-Control-Allow-Origin').“ ”已阻止跨源请求:同源策略禁止读取位于 ******的远程资源.(原因:CORS 请求失败).“ 在项目中或者练习中经常遇到ajax请求跨域的问题,除了可以用jsonp的请求模式,并且在后台支持回调的方式以外,还可以通过简单的配置webconfig文件或者IIS,解决该问题. 一.通过修改配置文件解决CORS跨域问题 在配置文件中的webse

CORS跨域请求总结

CORS跨域请求分为简单请求和复杂请求. 1. 简单请求: 满足一下两个条件的请求. (1) 请求方法是以下三种方法之一: HEAD GET POST (2)HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded.multipart/form-data.text/plain 2. 复杂请求: 非简单请求

jquery ajax CORS 跨域访问 WebService

JS代码: var word = document.getElementById("word").value; $.ajax({ type: "POST", contentType: "application/x-www-form-urlencoded", url: "http://localhost:12805/WebService.asmx/HelloWorld", data: 'data=' + word, dataTy

ajax——CORS跨域调用REST API 的常见问题以及前后端的设置

RESTful架构是目前比较流行的一种互联网软件架构,在此架构之下的浏览器前端和手机端能共用后端接口. 但是涉及到js跨域调用接口总是很头疼,下边就跟着chrome的报错信息一起来解决一下. 假设:前端域名为front.ls-la.me,后端域名为api.ls-la.com.前端需要访问的接口为http://api.ls-la.com/user/info.json,需要用GET方式访问. 现在,用Ajax向后端发送请求,得到第一个错误.(cors跨域的写法参考:http://blog.csdn.

CORS跨域详解

废话少数,直接上代码!!!!!!!!!! html: <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Document</title>      <script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.js"