AJAX的跨域请求
JSONP
使用script标签向服务器请求一个脚本,这不受跨域影响,所以可以为script标签的src参数填写URL时增加一个查询参数来指定返回结果时的回调函数,让服务器返回的脚本信息是调用该回调函数的脚本,限制就是只能是GET请求
示例
function addScriptTag(src) { //动态的插入script标签,请求地址由外部传入
var script = document.createElement("script"); //创建script标签
script.setAttribute("type", "text/javascript"); //添加该属性表示是javascrip脚本
script.src = src; //添加src属性为要请求的地址
document.body.appendChild(script); //将该script插入到页面中
}
function fun(data){ //服务器一旦返回直接调用的该函数
console.log(data.id); //由于要求服务器返回的是JavaScript脚本,参数就是对象,所以可以直接以对象形式调用
}
window.onload = function () { //当页面加载时
addScriptTag("http://www.baidu.com/?callback=fun"); //调用jsonp跨域请求
//服务器收到这个请求后需要返回以下形式脚本数据
//fun({
// id:1,
// name:zhangsan
//})
}
WebSocket
使用WebSocket进行协议进行通信,该协议不实行同源政策,只要服务器支持,就可以通过他进行跨域通信
CORS(跨域资源共享)
需要浏览器和服务器都支持,目前所有浏览器都支持,整个CORS通信过程,浏览器都是自动完成的,浏览器一旦发现AJAX请求跨域,就会自动附加一些头部信息,所以实现CORS通信的关机是服务器
简单请求
简单的说简单请求就是简单的请求方法和简单的请求头的结合,表单请求也是简单请求,表单请求在历史上是一直可以跨域请求的
-
请求方法是:
HEAD、GET、POST -
请求头只有:
AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:仅限三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求流程
浏览器直接发出CORS请求,在请求头中添加一个Origin字段来标明本次请求来自哪个域(协议+域名+端口)
- 若该域不在许可范围内,服务器会返回一个正常的HTTP响应,这个正常的响应中没有包含
Access-Control-Allow-Origin字段,所以浏览器就会忽略掉接收请求,就会抛出一个错误被XMLHttpRequest的onerror回调函数捕获,这种错误是无法使用状态码来判断的,因为是一个正常的HTTP响应 - 若该域在许可范围内,服务器就会在响应头中添加以下三个字段
Access-Control-Allow-Origin:该字段是必须的,要么是*表示可接受任意域请求,要么与请求时的Origin的值相同(要注意域名和IP的映射关系浏览器是不知道的,所以也属于不同域,而且只能设置一个值,若想设置多个就需要在程序中实现)Access-Control-Allow-Credentials:该字段可选,它的值是一个布尔值,表示是否允许浏览器发送Cookie,默认不发送(不设置就相当于false),只能设置为true;若只是将XMLHttpRequest的withCredentials设置为true,但是服务器不允许发送Cookie,则浏览器不会将响应内容返回给请求者,只有两者同时为true才行;设置上传Cookie后Access-Control-Allow-Origin字段就不能使用*,必须与请求网页同域,Cookie依然遵循同源政策,也就是上传是AJAX请求域的Cookie而不是当前页面的Cookie,当前页面也无法拿到AJAX请求域的CookieAccess-Control-Expose-Headers:该字段可选,在CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个服务器返回的基本字段,若想使用该方法拿到其他的字段(包括自定义字段)就需要在该字段指定;6个基本字段包括:``Cache-Control、Content-Language、Content-Type、Expires、Last-Modified和Pragma`
非简单请求
非简单请求的CORS请求,会在正式通信前增加一次HTTP查询请求,询问服务器当前页面域名是否在服务器允许跨域白名单中,以及可以使用哪些HTTP方法和请求头字段,只有得到肯定的答复,浏览器才会发出正式的AJAX请求,否则就会报错
比如:请求方法是PUT或DELETE,Content-Type字段的类型是application/json
1. 预检请求
- 预检请求使用的是
OPTIONS方法 - 主要有这几个字段来进行询问
Origin:标明请求来自哪个域Access-Control-Request-Method:要使用的请求方法Access-Control-Request-Headers:要使用哪些自定义请求头字段,多个可使用逗号分隔
2. 预检请求响应
- 主要有对应的字段来进行响应
Access-Control-Allow-Origin:允许跨域的域Access-Control-Allow-Methods:允许使用的请求方法,多个用逗号分隔Access-Control-Allow-Headers:允许使用的自定义请求头字段,多个用逗号分隔Access-Control-Allow-Credentials:是否需要发送Cookie,与简单请求中的一致Access-Control-Max-Age:指定多久之内不需要在发送预检请求,以秒为单位
- 允许:上述的字段的值都应该大于等于(预检请求的值都包含在预检响应中)请求允许
- 不允许:返回一个正常的HTTP响应,但是没有任何CORS相关字段或者明确表示请求不符合条件,这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被
XMLHttpRequest对象的onerror回调函数捕获
3. 浏览器的正常请求和响应
一旦预检请求通过后,就都跟简单请求一样,请求头会增加一个Origin头信息字段,响应体会增加一个Access-Control-Allow-Origin字段

Comments NOTHING