1. Intro
在用ajax请求时,请求的域名和所在域名不同,会出现跨域问题导致请求失败。
复杂请求:
条件: 1、请求方式:HEAD、GET、POST 2、请求头信息: Accept Accept-Language Content-Language Last-Event-ID Content-Type 对应的值是以下三个中的任意一个 application/x-www-form-urlencoded multipart/form-data text/plain 注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
2. 简单请求
2.1 JSONP
function jsonp(url) { // url 一般带有参数用来决定下面func1的名称 例如: http://127.0.0.1:7766/SendAjax/?callbacks=func1 但是这个callback参数的名称是服务端定的
let newlabel = document.createElement("script"); // 添加标签 newlabel.src = url document.body.appendChild(newlabel) // 加到文档中 script.setAttribute("type","text/javascript") document.body.removeChild(newlabel) // 删除标签 } function func1(data){ // 这里定义注意名称func1 alert(data) // 这里对数据进行处理 }
jsonp(url) // 调用jsonp函数
// 这里jsonp函数会建立并删除一个script标签,其中包含了从前端拿来的数据:func1(data) 通过这个数据调用fun1函数
$.ajax({ url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403", dataType: 'jsonp', jsonp: 'callback', jsonpCallback: 'list', success:function (data) { // 处理 }})
服务端:
callbacks=request.GET.get("callbacks") // 拿到callback参数 return HttpResponse(callback +"("+ json.dumps(DATA)+")") // 返回callback()
JSONP格式只能发GET请求
2.2 CORS
服务端返回头设置 "Access-Control-Allow-Origin" = "*"
* 代表具体域名,也可以写*代表全部域名
这种方法不限制请求方法
3. 复杂请求
3.1 请求过程
复杂请求浏览器会先发一个option请求进行preflight request (预检),这时候需要浏览器返回带有相关头信息的回应。
3.2 请求处理
根据不同的情况设置返回信息头:
"Access-Control-Allow-Origin" // 跨域必写
"Access-Control-Allow-Headers" // 允许的自定义请求头内容
"Access-Control-Allow-Method" // 大写例如PUT
3.3 暴露自定义相应头
function JqSendRequest(){ $.ajax({ url: "http://c2.com:8000/test/", type: 'PUT', dataType: 'text', headers: {'k1': 'v1'}, success: function(data, statusText, xmlHttpRequest){ console.log(data); // 获取响应头 console.log(xmlHttpRequest.getAllResponseHeaders()); } }) }
返回头:
//自定义返回头: "aaa" "bbb" "ccc" "ddd" //为了暴露自定义返回头需要加 “Access-Control-Expose-Headers' "xxoo,bili" 注意: 该部分不在option预检返回头部分。 “Access-Control-Expose-Headers' 应与自定义头一起放在正常返回头中
3.4 跨域传cookie
在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。
要求
- 浏览器端:XMLHttpRequest的withCredentials为true, fetch API 设置
credentials为include
- 服务器端:Access-Control-Allow-Credentials为true
- 注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符
3.5 Access-Control-Max-Age
Access-Control-Max-Age 这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久。 所以一定要设置在option请求的返回头中。