关于浏览器跨域问题Access-Control-Allow-Origin

吃可爱长大的小学妹 提交于 2019-11-28 20:42:31

其实很早就接触过前端开发 也处理过跨域问题(当时采用的是jsonp server+client 都要改动。。。。)

现在这段时间也在做这块 记录+整理

跨域问题是什么gui?

一个网站的网址组成包括协议名,域名,端口号。比如 http://www.sagosoft.com,其中http是协议名,www.sagosoft.com是域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。
即使是在 http://localhost:8080/ 页面请求 http://127.0.0.1:8080/ 也会有跨域问题


跨域问题制约哪些操作?

常见的不同域间的页面制约dom元素包括:

         window.location 可以设置,但不能读取。其它的 location 属性和方法被禁止访问; 
        document.href 可以设置,但不能读取。其它的 document 属性和方法被禁止访问; 
        <iframe> 的 src 可以设置,但不能读取

ajax访问无返回值??

由于安全原因,跨域访问是被各大浏览器所默认禁止的;但是浏览器并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function

解决跨域问题

解决跨域问题有以下tri种方式

  • 使用jsonp

  • 服务端代理

  • 服务端设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名

jsonp的解决方式(仅支持GET方式)

json≠jsonp

原理

jsonp解决跨域问题的原理是,浏览器的script标签是不受同源策略限制(你可以在你的网页中设置scriptsrc属性问cdn服务器中静态文件的路径)。那么就可以使用script标签从服务器获取数据,请求时添加一个参数为callbakc=?,?号时你要执行的回调方法。

前端实现

以jQuery2.1.3的ajax方法为例

$.ajax({
    url:"",
    dataType:"jsonp",
    data:{
        params:""
        }
}).done(function(data){    //dosomething..})

仅仅是客户端使用jsonp请求数据是不行的,因为jsonp的请求是放在script标签中的,和普通请求不同的地方在于,它请求到的是一段js代码,如果服务端返回了json字符串,那么浏览器就会报错。所以jsonp返回数据需要服务端做一些处理。

服务端返回数据处理

上面说了jsonp的原理是利用script标签来解决跨域,但是script标签是用来获取js代码的,那么我们怎么获取到请求的数据呢。

这就需要服务端做一些判断,当参数中带有callback属性时,返回的type要为application/javascript,把数据作为callback的参数执行。下面是jsonp返回的数据的格式示例

/* typeof jQuery21307270454438403249_1428044213638 === 'function'*/ 
jQuery21307270454438403249_1428044213638({"code":1,"msg":"success","data":{"test":"test"}});

这是express4.12.3关于jsonp的实现代码

if (typeof callback === 'string' && callback.length !== 0) {
	this.charset = 'utf-8';
	this.set('X-Content-Type-Options', 'nosniff');
	this.set('Content-Type', 'text/javascript'); // restrict callback charset
	// replace chars not allowed in JavaScript that are in JSON
	callback = callback.replace(/[^\[\]\w$.]/g, ''); 
	body = body.replace(/\u2028/g, '\\u2028')
		.replace(/\u2029/g, '\\u2029');
		 // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse"
		// the typeof check is just to reduce client error noise
		body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body                 + ');';
}


服务端设置Access-Control-Allow-Origin(CORS

这种方式只要服务端把response的header头中设置Access-Control-Allow-Origin为制定可请求当前域名下数据的域名即可。一般情况下设为即可。这样客户端就不需要使用jsonp来获取数据。

会有安全问题(更多请百度)

但是个人是用这个方法的

CORS支持POST提交,并且实施起来嘿简单,CORS原理:只需要向响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作。

我用的是php,用法如:(*号也可以指定特定的域名,只允许该域名访问)

 <?php
    header("Access-Control-Allow-Origin:*"); 
    //...

如果是java,

response.setHeader("Access-Control-Allow-Origin", "*");

浏览器支持

Access-Control-Allow-Origin是html5新增的一项标准,IE10以下是不支持的,所以如果产品面向的是PC端,就要使用服务端代理或jsonp。

见图

====================================================================

主要解决方案 :

 jsonp    (jquery-jsonp插件也可)

CORS

服务端代理通过在同域名下的web服务器端创建一个代理,这个需要在服务器端做 服务器的负荷+++

nginx反向代理

<script> 跨域获取资源(要求返回的是正规的js对象格式 如json、js数组)

隐藏iframe、共享domain只适用在具有同一个父域下的跨域请求上


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!