04-AJAX的跨域请求

nobility 发布于 2023-05-19 07-AJAX 2450 次阅读


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通信的关机是服务器

简单请求

简单的说简单请求就是简单的请求方法和简单的请求头的结合,表单请求也是简单请求,表单请求在历史上是一直可以跨域请求的

  • 请求方法是:HEADGETPOST

  • 请求头只有:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:仅限三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

简单请求流程

浏览器直接发出CORS请求,在请求头中添加一个Origin字段来标明本次请求来自哪个域(协议+域名+端口)

  • 若该域不在许可范围内,服务器会返回一个正常的HTTP响应,这个正常的响应中没有包含Access-Control-Allow-Origin字段,所以浏览器就会忽略掉接收请求,就会抛出一个错误被XMLHttpRequestonerror回调函数捕获,这种错误是无法使用状态码来判断的,因为是一个正常的HTTP响应
  • 若该域在许可范围内,服务器就会在响应头中添加以下三个字段
    • Access-Control-Allow-Origin:该字段是必须的,要么是*表示可接受任意域请求,要么与请求时的Origin的值相同(要注意域名和IP的映射关系浏览器是不知道的,所以也属于不同域,而且只能设置一个值,若想设置多个就需要在程序中实现)
    • Access-Control-Allow-Credentials:该字段可选,它的值是一个布尔值,表示是否允许浏览器发送Cookie,默认不发送(不设置就相当于false),只能设置为true;若只是将XMLHttpRequestwithCredentials设置为true,但是服务器不允许发送Cookie,则浏览器不会将响应内容返回给请求者,只有两者同时为true才行;设置上传Cookie后Access-Control-Allow-Origin字段就不能使用*,必须与请求网页同域,Cookie依然遵循同源政策,也就是上传是AJAX请求域的Cookie而不是当前页面的Cookie,当前页面也无法拿到AJAX请求域的Cookie
    • Access-Control-Expose-Headers:该字段可选,在CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个服务器返回的基本字段,若想使用该方法拿到其他的字段(包括自定义字段)就需要在该字段指定;6个基本字段包括:``Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma`

非简单请求

非简单请求的CORS请求,会在正式通信前增加一次HTTP查询请求,询问服务器当前页面域名是否在服务器允许跨域白名单中,以及可以使用哪些HTTP方法和请求头字段,只有得到肯定的答复,浏览器才会发出正式的AJAX请求,否则就会报错

比如:请求方法是PUTDELETEContent-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字段

加油啊!即便没有转生到异世界,也要拿出真本事!!!\(`Δ’)/
最后更新于 2023-05-19