前端web:主流跨域方式有哪些?

栏目: 编程语言 · XML · 发布时间: 5年前

内容简介:举例:不进行预检请求的http请求,称为简单请求;如下是一个需要执行预检请求的 HTTP 请求:
  • 不允许跨域的基本原因是:http请求头中没有允许跨域有关的参数。解决跨域请求的原理就是在拦截器中拦截请求,请在Http请求头添加允许跨域的字段

jspnp 跨域请求

  • jsonp的缺点就是只能采用get请求。
    • 为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许
    • 基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
$.ajax({
                url: 'http://localhost:1112/getPerson?callback=?',
                dataType: 'jsonp',
                jsonpCallback: 'person',
                success: function(data){
                    $('.name').html(data.name);
                    $('.company').html(data.company);
                }
            })

复制代码

cors(cross-origin-resource-share) 跨域资源共享:

cors机制:

  • 它使用额外的HTTP头来告诉浏览器,让运行在一个origin上的web应用被准许访问来自不同源服务器上的指定资源。
  • 当一个资源从与该资源本身所在的服务器不同的域/协议/端口请求一个资源的时候,资源会发起一个跨域请求;

举例:

  • 站点http://domain-a.com 的某html页面通过src 请求http://domain-b.com/imge.jpg;
  • 网络上的许多页面加载来自不同域的css样式表/图像/和脚本等资源;

处于安全原因:

  • 浏览器限制从脚本内发起http跨域请求,或者是跨站请求可以正常发起,但是返回结果被浏览器拦截了 例如:XMLHttpRequest 和 fetch发起的请求;
  • cors机制,允许web应用服务器进行跨域访问控制,从而是的跨域访问数据传输得以安全进行;

API遵循同源策略:

  • 这意味着使用这些API的Web应用程序,只能从加载应用程序的同一个域请求HTTP资源, 除非 响应报文包含了正确CORS响应头。
前端web:主流跨域方式有哪些?

新增CORS标准:

  • 跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源;
  • 对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

cors举例:

比如说,假如站点 http://foo.example 的网页应用想要访问 http://bar.other 的资源。http://foo.example 的网页中可能包含类似于下面的 JavaScript 代码:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';
   
function callOtherDomain() {
  if(invocation) {    
    invocation.open('GET', url, true);
    invocation.onreadystatechange = handler;
    invocation.send(); 
  }
}
复制代码

简单请求:

不进行预检请求的http请求,称为简单请求;

前端web:主流跨域方式有哪些?
Request:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example

Response:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61 
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]
复制代码

预检请求:

  • “需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。
  • "预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

预检请求条件:

1.使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
2.人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
3.Content-Type 的值不属于下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
4.请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器。
5.请求中使用了ReadableStream对象。
复制代码

如下是一个需要执行预检请求的 HTTP 请求:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}

......
复制代码
前端web:主流跨域方式有哪些?
Request:

 1.OPTIONS /resources/post-here/ HTTP/1.1
 2.Host: bar.other
 3.User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
 4.Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 5.Accept-Language: en-us,en;q=0.5
 6.Accept-Encoding: gzip,deflate
 7.Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
 8.Connection: keep-alive
 9.Origin: http://foo.example
10.Access-Control-Request-Method: POST
11.Access-Control-Request-Headers: X-PINGOTHER, Content-Type

Response:

14.HTTP/1.1 200 OK
15.Date: Mon, 01 Dec 2008 01:15:39 GMT
16.Server: Apache/2.0.61 (Unix)
17.Access-Control-Allow-Origin: http://foo.example
18.Access-Control-Allow-Methods: POST, GET, OPTIONS
19.Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
20.Access-Control-Max-Age: 86400
21.Vary: Accept-Encoding, Origin
22.Content-Encoding: gzip
23.Content-Length: 0
24.Keep-Alive: timeout=2, max=100
25.Connection: Keep-Alive
26.Content-Type: text/plain
复制代码

预检请求完成之后,发送实际请求:

POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache

<?xml version="1.0"?><person><name>Arun</name></person>


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]

首部字段 Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求
复制代码

附带身份凭证的请求:

Fetch 与 CORS 的一个有趣的特性是,可以基于 HTTP cookies 和 HTTP 认证信息发送身份凭证。一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。

本例中,foo.example 的某脚本向bar.other 发起一个GET 请求,并设置 Cookies:

var invocation = new XMLHttpRequest(); var url = ' bar.other/resources/c… ';

function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send();

} }

  • withCredentials 标志设置为 true,从而向服务器发送 Cookies
  • 因为这是一个简单 GET 请求,所以浏览器不会对其发起“预检请求”。但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。
前端web:主流跨域方式有哪些?

附带身份凭证的请求与通配符

  • 附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。

这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为foo.example,则请求将成功执行。

HTTP 响应首部字段

Access-Control-Allow-Origin

响应首部中可以携带一个 Access-Control-Allow-Origin 字段,其语法如下:

Access-Control-Allow-Origin: <origin> | *
复制代码

其中:

  • origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。

例如,下面的字段值将允许来自mozilla.com 的请求:

Access-Control-Allow-Origin: http://mozilla.com
复制代码

如果服务端指定了具体的域名而非“*”,那么响应首部中的 Vary 字段的值必须包含 Origin。这将告诉客户端:服务器对不同的源站返回不同的内容。

Access-Control-Allow-Credentials

  • Access-Control-Allow-Credentials头指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。
  • 当用在对preflight预检测请求的响应中时,它指定了实际的请求是否可以使用credentials。请注意:简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。
Access-Control-Allow-Credentials: true
复制代码

HTTP 请求首部字段

Origin

Origin 首部字段表明预检请求或实际请求的源站。

Origin: <origin>
复制代码

origin 参数的值为源站 URI。它不包含任何路径信息,只是服务器名称。

Access-Control-Request-Headers

Access-Control-Request-Headers 首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。

Access-Control-Request-Headers: <field-name>[, <field-name>]*
复制代码

参考MDN


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design for Hackers

Design for Hackers

David Kadavy / Wiley / 2011-10-18 / USD 39.99

Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具