JavaScript:CORS(跨源资源共享)

  XHR的一个主要约束是同源策略,即:相同域、相同端口、相同协议,可以通过跨域资源共享CORS(Cross-Origin Resourse Sharing)实现跨域资源共享。其基本思想是通过自定义HTTP头让浏览器与服务器沟通,从而决定请求或响应是应该成功还是失败。发送get/post请求时,给它添加一个额外的Origin头部,其中包含请求页面的源信息(协议,域名和端口),以便服务器根据这个头部信息来决定是否响应,像这样的:Origin:http://www.nczonline.net。如果服务器认为这个请求可以接受,就在头部发回相同的源信息:Access-Control-Allow-Origin:http://www.nczonline.net。如果没有这个头部或者源信息不匹配,那么服务器就会驳回请求,正常的情况下浏览器会处理请求。

  跨域请求,就是一个站点中的资源去访问另外一个不同域名站点上的资源。这种情况很常见,比如说通过 <link> 标签加载外部样式表文件、通过 <img> 标签加载外部图片、通过 <script> 标签加载外部脚本文件等等。默认情况下,脚本访问文档属性等数据采用的是同源策略(Same origin policy)。

那么,什么是同源策略呢?如果两个页面的协议、域名和端口是完全相同的,那么它们就是同源的。 如果两个页面的主域名相同,则还可以通过设置 document.domain 属性将它们认为是同源的。

(1)、IE对CORS支持——XDR(XDomainRequest)

  IE中使用XDR对象实现CORS,它的使用与XHR对象类似,也是实例化后调用open()和send()方法。不同的是,XDR的open()方法只有两个参数:请求类型和URL,默认异步请求。

  XDR和XHR的一些不同之处:

   cookie不会随请求发送,也不会随响应返回。

   只能设置请求头部信息中的Content-Type字段。

   不能访问响应头部信息。

   只支持GET和POST请求

var xdr= new XDomainRequest();
xdr.οnlοad=function(){
  alert(xhr.responseText);
}
xdr.οnerrοr=function(){
  alert("An error occurred");
}
xdr.timeout=1000;
xdr.ontimeout=function(){
  alert("Request took too long");
}
xhr.open("get","http://www.other.com");
xdr.contentType="application/x-www-form-urlencoded";
xhr.send("name1=value1&name2=value2");

(2)、其他浏览器支持CORS——原生XHR

  大多数浏览器的XHR对象原生支持CORS,只需要在open()方法中传入响应的url即可。与IE中的XDR对象不同,通过跨域XHR对象可以访问status和statusText属性,而且还支持同步请求。但是也有以下限制:

  不能使用setRequestHeader()设置自定义头部。

  不能发送和接收cookie。

  调用getAllRequestHeaders()方法总返回空字符串。

(3)、跨浏览器支持CORS

  综合以上两种情况,可以实现跨浏览器的CORS。检查XHR是否支持CORS的最简单方式是检查 withCredentials属性,然后结合检查XDomainRequest对象是否存在即可。

(4)、简单请求

  什么样的请求算是简单请求呢?简单请求必须满足下面2点:

   A、只使用 GET、POST 进行的请求,这里的POST只包括发送给服务器的数据类型(Content-Type)必须是 application/x-www-form-urlencoded、multipart/form-data 或者 text/plain中一个。

   B、HTTP 请求没有设置自定义的请求头,如我们常用的 X-JSON。

   客户端:

        var xhr = new XMLHttpRequest();  
        var url = 'http://dotnet.aspx.cc/SimpleCrossSiteRequests.aspx';  
        xhr.open('GET', url, true);  
        xhr.onreadystatechange = handler;  
        xhr.send();

    服务器端:

     Response.AddHeader("Access-Control-Allow-Origin", "http://www.meng_xian_hui.com:801");  
     Response.Write("你的第一个跨域测试成功啦!!!");

 

  需要特别注意的是:在请求信息中,浏览器使用 Origin 这个 HTTP 头来标识该请求来自于 http://www.meng_xian_hui.com:801;在返回的响应信息中,使用 Access-Control-Allow-Origin 头来控制哪些域名的脚本可以访问该资源。如果设置 Access-Control-Allow-Origin:*,则允许所有域名的脚本访问该资源。如果有多个,则只需要使用逗号分隔开即可。

(5)、预检请求

  预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTIONS 请求头,其目的就是为了判断实际发送的请求是否是安全的。下面的2种情况需要进行预检:

   A、不是上面的简单请求,比如使用Content-Type 为 application/xml 或 text/xml 的 POST 请求

   B、在请求中设置自定义头,比如 X-JSON、X-MENGXIANHUI 等

    客户端:        

        var xml = "<root>测试</root>";  
        xhr.open('POST', url, true);  
        xhr.setRequestHeader("POWERED-BY-MENGXIANHUI","Approve");  
        xhr.setRequestHeader("Content-Type", "application/xml");  
        xhr.onreadystatechange = handler;  
        xhr.send(xml);

    服务器端://通知客户端允许预检请求。并设置缓存时间  

        Response.ClearContent();  
        Response.AddHeader("Access-Control-Allow-Origin", "http://www.meng_xian_hui.com:801");  
        Response.AddHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS");  
        Response.AddHeader("Access-Control-Allow-Headers", "POWERED-BY-MENGXIANHUI");  
        Response.AddHeader("Access-Control-Max-Age", "30");    
        //此过程无需返回数据  
        Response.End();

  以上的代码反映了预检请求的执行过程:首先发送 OPTIONS 请求头,用来向服务器咨询服务器的更多信息,以便为后续的真实请求做准备。比如是否支持 POST 方法等。值得注意的是:浏览器还发送 Access-Control-Request-Method: POST 和 Access-Control-Request-Headers:POWERED-BY-MENGXIANHU请求头。  

(6)、带验证信息的请求

  XMLHttpRequest和访问控制功能,最有趣的特性就是,发送凭证请求(HTTP Cookies和验证信息)的功能。一般而言,对于跨站请求,浏览器是不会发送凭证信息的。但如果将XMLHttpRequest的一个特殊标志位设置为true,浏览器就将允许该请求的发送。身份验证是Web开发中经常遇到的问题,在跨域请求中,默认情况下是不发送验证信息的。要想发送验证信息,需要进行withCredentials 属性,

  客户端:

    var xhr = new XMLHttpRequest();  
    var url = 'http://dotnet.aspx.cc/RequestsWithCredentials.aspx';  
    xhr.open('GET', url, true);  
    xhr.onreadystatechange = handler;  
    xhr.withCredentials = "true";  
    xhr.send();  
  浏览器端:

    Access-Control-Allow-Origin: http://www.meng_xian_hui.com:801  
    Access-Control-Allow-Credentials: true 

  将XMLHttpRequest的withCredentials标志设置为true,从而使得Cookies可以随着请求发送。因为这是一个简单的GET请求,所以浏览器不会发送一个“预请求”。但是,如果服务器端的响应中,如果没有返回Access-Control-Allow-Credentials: true的响应头,那么浏览器将不会把响应结果传递给发出请求的脚步程序,以保证信息的安全。

  特别注意: 给一个带有withCredentials的请求发送响应的时候,服务器端必须指定允许请求的域名,不能使用'*'.上面这个例子中,如果响应头是这样的:Access-Control-Allow-Origin: * ,则响应会失败. 在这个例子里,因为Access-Control-Allow-Origin的值是http://www.meng_xian_hui.com:801这个指定的请求域名,所以客户端把带有凭证信息的内容被返回给了客户端.

(7)、IE8已经开始支持跨域访问资源了,但是,IE8提供的功能还比较简单,可以进行简单的请求,

   客户端:

        var xhr = new XDomainRequest();   
        var url = 'http://dotnet.aspx.cc/SimpleCrossSiteRequests.aspx';  
        xhr.open('GET', url, true);  
        xhr.onreadystatechange = handler;  
        xhr.send();

   服务器端:

        Response.AddHeader("Access-Control-Allow-Origin", "http://www.meng_xian_hui.com:801");  
        Response.Write("你的第一个跨域测试成功啦!!!");

(8)、HTTP响应头

  这部分里列出了跨域资源共享(Cross-Origin Resource Sharing)时,服务器端需要返回的响应头信息.上一部分内容是这部分内容在实际运用中的一个概述.

Access-Control-Allow-Origin

  返回的资源需要有一个 Access-Control-Allow-Origin 头信息,语法如下:

           Access-Control-Allow-Origin: <origin> | *

  origin参数指定一个允许向该服务器提交请求的URI.对于一个不带有withCredentials的请求,可以指定为'*',表示允许来自所有域的请求.

  举个栗子,允许来自 http://mozilla.com 的请求,你可以这样指定:

           Access-Control-Allow-Origin: http://mozilla.com

  如果服务器端指定了域名,而不是'*',那么响应头的Vary值里必须包含Origin.它告诉客户端: 响应是根据请求头里的Origin的值来返回不同的内容的.

Access-Control-Expose-Headers

  设置浏览器允许访问的服务器的头信息的白名单:

      Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

  这样, X-My-Custom-Header 和 X-Another-Custom-Header这两个头信息,都可以被浏览器得到.

Access-Control-Max-Age

  这个头告诉我们这次预请求的结果的有效期是多久,如下:

      Access-Control-Max-Age: <delta-seconds>

  delta-seconds 参数表示,允许这个预请求的参数缓存的秒数,在此期间,不用发出另一条预检请求.

Access-Control-Allow-Credentials

  告知客户端,当请求的withCredentials属性是true的时候,响应是否可以被得到.当它作为预请求的响应的一部分时,它用来告知实际的请求是否使用了withCredentials.注意,简单的GET请求不会预检,所以如果一个请求是为了得到一个带有withCredentials的资源,而响应里又没有Access-Control-Allow-Credentials头信息,那么说明这个响应被忽略了.

      Access-Control-Allow-Credentials: true | false

Access-Control-Allow-Methods

  指明资源可以被请求的方式有哪些(一个或者多个). 这个响应头信息在客户端发出预检请求的时候会被返回. 上面有相关的例子.

     Access-Control-Allow-Methods: <method>[, <method>]*

Access-Control-Allow-Headers

  也是在响应预检请求的时候使用.用来指明在实际的请求中,可以使用哪些自定义HTTP请求头.比如

     Access-Control-Allow-Headers: X-PINGOTHER

  这样在实际的请求里,请求头信息里就可以有这么一条:

      X-PINGOTHER: pingpong

  可以有多个自定义HTTP请求头,用逗号分隔.

      Access-Control-Allow-Headers: <field-name>[, <field-name>]*


(9)、HTTP 请求头

  这部分内容列出来当浏览器发出跨域请求时可能用到的HTTP请求头.注意这些请求头信息都是在请求服务器的时候已经为你设置好的,当开发者使用跨域的XMLHttpRequest的时候,不需要手动的设置这些头信息.

Origin:表明发送请求或者预请求的域

  Origin: <origin>

  参数origin是一个URI,告诉服务器端,请求来自哪里.它不包含任何路径信息,只是服务器名.

  Note: Origin的值可以是一个空字符串,这是很有用的.

  注意,不仅仅是跨域请求,普通请求也会带有ORIGIN头信息.

Access-Control-Request-Method

  在发出预检请求时带有这个头信息,告诉服务器在实际请求时会使用的请求方式

     Access-Control-Request-Method: <method>

Access-Control-Request-Headers

  在发出预检请求时带有这个头信息,告诉服务器在实际请求时会携带的自定义头信息.如有多个,可以用逗号分开.

      Access-Control-Request-Headers: <field-name>[, <field-name>]*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要关闭CORS(跨站资源共享),您需要在服务器端进行配置。以下是一些常见的方法: 1. 在后端服务器中进行配置:在服务器端代码中添加响应头,以允许来自其他域的请求访问资源。具体的配置方法因服务器而异,以下是一些示例代码: - Node.js(使用Express框架): ```javascript const express = require('express'); const app = express(); // 允许所有域的请求访问资源 app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); next(); }); // 其他路由和中间件配置... app.listen(3000, () => { console.log('Server started on port 3000'); }); ``` - Java(使用Spring框架): ```java import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @CrossOrigin(origins = "*") public class ExampleController { @GetMapping("/example") public String getExample() { return "Hello, CORS!"; } // 其他方法... } ``` 2. 使用代理服务器:如果您的前端应用程序在与后端服务器不同的域上运行(例如,前端在localhost:3000,后端在localhost:8000),您可以设置一个代理服务器来转发请求。这样,前端应用程序将发送请求给代理服务器,然后由代理服务器将请求转发给后端服务器,避免CORS问题。 3. 在特定的Web服务器上进行配置:例如,对于Apache服务器,您可以在.htaccess文件中添加以下内容: ``` Header set Access-Control-Allow-Origin "*" ``` 对于Nginx服务器,您可以在配置文件的server块中添加以下内容: ``` location / { add_header 'Access-Control-Allow-Origin' '*'; # 其他配置项... } ``` 请注意,关闭CORS可能会带来安全风险。在生产环境中,您应该谨慎考虑是否真的需要关闭CORS,并且根据需要配置允许访问的域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值