说说跨域

日期:2013-4-19 13:51 | 标签: | 阅读:524

说到跨域,就不得不谈jsonp,原理非常简单,即允许用户传递一个callback参数给服务端,服务端返回数据时将这个callback参数作为函数名来包裹JSON数据,这样客户端就可以定制自己的函数来自动处理返回数据了,事实上,除了json,几乎所有带src属性的标签都有跨域功能,如img、script(jsonp基于此)、iframe:性能差、难维护。
当然,我们也可以通过于服务端的跨域协商实现跨域。

跨域HTTP头

简单跨域请求

简单跨求请求定义

  1. 请求方法是GET、HEAD或者POST,并且当请求方法是POST时,Content-Type必须是application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值。
  2. 请求中没有自定义HTTP头部。

服务端要做是在在响应头中添加Access-Control-Allow-Origin Header。 浏览器收到确认授权消息后即将结果移交至js处理。

预检跨域请求

非简单跨域请求。类似这种:

xhr.setRequestHeader("Y-key", "Y-value");

服务器可以设置

// 授权的源控制
Access-Control-Allow-Origin: <origin> | * 
// 授权的时间,允许浏览器在指定时间内,无需再发送预检请求进行协商
Access-Control-Max-Age: <delta-seconds> 
 // 控制是否开启与Ajax的Cookie提交方式
Access-Control-Allow-Credentials: true | false
// 允许请求的HTTP Method
Access-Control-Allow-Methods: <method>[, <method>]* 
// 控制哪些header能发送真正的请求    
Access-Control-Allow-Headers: <field-name>[, <field-name>]*

浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。这个过程对真实请求的调用者来说是透明的。
XMLHttpRequest支持通过withCredentials属性实现在跨域请求携带身份信息(Credential,例如Cookie或者HTTP认证信息)。浏览器将携带Cookie Header的请求发送到服务器端后,如果服务器没有响应Access-Control-Allow-Credentials Header,那么浏览器会忽略掉这次响应。

// 客户端设置
xhr.withCredentials = true;

// 服务端设置
Access-Control-Allow-Credentials: true

// ====angularjs====
$http.post(url, {withCredentials: true, ...})
$http({withCredentials: true, ...}).post(...)
.config(function ($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
}

// ====jquery====
$.ajax("url", {
  type: "POST",
  xhrFields: {
    withCredentials: true
  },
  crossDomain: true,
  success: function(data, status, xhr) {}
});

只要是带自定义header的跨域请求,在发送真实请求前都会先发送OPTIONS请求,浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。所以复杂请求肯定会两次请求服务端。

参考

张水清ppt分享: 链接
IE中iframe和document.selection.createRange导致跨域(张水清): 链接
zhuwenlong博客:
https://www.zhuwenlong.com/blog/article/5524f05cfd9753d106000001
js设置跨域请求头: http://blog.csdn.net/enter89/article/details/51205752

版权声明: 署名-非商业性使用-禁止演绎 4.0 国际(CC BY-NC-ND 4.0
Copyright ©2013-2017 | 粤ICP备14081691号 | yipeng手工打造 | 联系方式