为了账号安全,请及时绑定邮箱和手机立即绑定

ajax跨域完全讲解

晓风轻 全栈工程师
难度中级
时长 1小时40分
学习人数
综合评分9.70
116人评价 查看评价
9.8 内容实用
9.6 简洁易懂
9.7 逻辑清晰
  • /*
    一.浏览器多管闲事-----------------------------------------------------搞定浏览器: 让浏览器滚,不判断
       1.启动浏览器的时候加参数
       2.浏览器跨域插件
    二.浏览器判断类型: XHR (XMLHttpRequest)-------------------------------发送类型不是XHR, JSONP就是利用这一条.
       JSONP一个非官方的协议, JSONP的弊端:
       1.JSONP需要后台配合, 要有一个参数, 默认是?callback=JQuery1234567...   JSONP返回的类型是:javascript, 而非json
       2.只可以发送get请求
       3.发送的不是XHR请求(这也是它可以跨域的原因),没有回调及事件的特性
    三.浏览器判断跨域: 协议, 域名, 端口, 任何一个不一样就是跨域-----------1.服务器告诉浏览器可以跨域. 2.前端通过代理欺骗浏览器是同一个域名
       1.后端处理:
          a)应用服务器(TOMCAT)--Filter,
             "Access-Control-Allow-Origin": "http://localhost:8081"
             "Access-Control-Allow-Methods": "GET"
             "Access-Control-Allow-Headers": "Content-Type, custom-header1, custom-header2" //非简单请求每次会发出去两次请求,预检命令(OPTIONS)和真正的请求
             "Access-Control-Max-Age": "3600" //预检命令(OPTIONS)为1个小时, 这样1个小时内就不用发送两次请求
             "Access-Control-Allow-Credentials": "true" //不是"Access-Control-Allow-Origin": "*"就无敌了, 带Cookie的请求就行不通!
          b)HTTP服务器(NGINX)
             配置比apache简单些
          c)HTTP服务器(APACHE)
             相对nginx复杂一些
          d)Spring框架解决方案
             @CrossOrigin
       2.前端处理(隐藏跨域):
          a)反向代理-NGINX配置
             在请求的时候写相对路径就行, 浏览器认为请求是同域的, 不会做跨域判断. 后端处理时, 请求地址都是绝对路径
          b)反向代理-APACHE配置
    
    以上一,二,三个条件必需同时满足, 才会生跨域问题!
    问答:
    -> 为什么已经返回200了还报错: 因为是先发送, 浏览器再判断是否跨域. 如果存在跨域条件, 则报错.
    */


  • JSONP的弊端:

    • 服务器需要改动代码支持-如果调用的接口不是我们自己的,那么改动就很麻烦

    • 只支持GET方法,JSONP是通过动态创建一个script发送请求的,而script只支持GET方法

    • 发送的不是XHR请求,XHR有许多新的特性,如异步、各种事件等,JSONP则没有


    04:07
    看视频
  • jsonp的实现原理:

    1. jsonp的请求类型是script,而非xhr,这样浏览器就不会做安全校验;

    2. jsonp的返回类型是js,而非json;

    3. jsonp请求携带一个前后台约定的参数(eg:callback),便于让后台识别是jsonp请求,后台则返回js数据而非json数据

    01:35
    看视频
  • 当浏览器要发送跨域请求时,如果请求是复杂请求,浏览器会先发送一个options预检命令即一个options请求,当该请求通过时才会再发送真正的请求。

    该option请求会根据请求的信息去询问服务端支不支持该请求。比如发送的数据是json类型(通过content-type设置)的话,会携带一个请求头Access-Control-Request-Headers: content-type去询问支不支持该数据类型,如果支持,则请求就会通过,并发送真正的请求


    07:05
    看视频
  • 总结

    跨域产生的原因:

    1. 浏览器限制。如果浏览器发现请求是跨域的时候,就会做校验,如果校验不通过就会报跨域的错误

    2. 跨域。发出去的请求只要域名、端口、协议中的任意一个与当前域不同的时候,都会发生跨域

    3. 发送的XHR(XMLHTTPRequest)请求。如果发送的不是xhr请求,无论是否跨域,浏览器都不会报错

    只有这三种原因同时满足时,才会发生跨域

    解决跨域的方法

    1. 浏览器角度。让浏览器不做校验,浏览器的设置跨域,在浏览器的属性设置页面的目标输入框加上--disable-web-security。这样浏览器将不会去做校验了。但是每个人都需要去改动,不建议使用。

    2. 发送xhr请求角度。让跨域的请求不发送xhr请求,就不会再报错了。办法是使用jsonp:jsonp是非官方协议,是前后端的一种约定,前端使用ajax发送请求,dataType为jsonp,并且带一个参数(默认是callback),当后台发现这个参数之后,就知道这是一个jsonp请求,就会把原本返回json对象编程js返回,js代码是一个函数的执行,函数名是callback的参数值,函数的参数是原本的json对象。缺点:1).只支持get方法请求;2).需要服务器修改代码;3).发送的不是xhr请求

    3. 在跨域角度。1).被调用方解决:在响应头增加指定字段,告诉浏览器,允许调用,这种方法的原理是从根源支持跨域的。各种解决方式,请参考详细解决笔记;2).调用方解决:这种解决办法原理是隐藏跨域。使用代理,在同一个域请求不同的url地址,转发到不同的域。


  • 一、解决跨域的思路:

    1.被调用方解决-支持跨域(根据http协议关于跨域方面的要求,增加响应头信息,告诉浏览器允许被跨域调用)

    (1)使用filter解决

    res.addHeader("Access-Control-Allow-Origin", "http://localhost:8081"); //设置允许http://localhost:8081域访问,*表示所有域都能访问

    res.addHeader("Access-Control-Allow-Methods", "GET");//设置允许GET方法访问,*表示所有方法

    (2)nginx解决方案

    (3)APACHE解决方案

    (4)Spring解决方案 加@CrossOrigin注解即可

    2.调用方使用代理做调用解决跨域问题-隐藏跨域

    (1)使用反向代理

    反向代理:访问同一个域名的两个url,会去到两个不同的服务器


    二、简单请求和非简单请求

    • 简单请求:先执行后判断

    工作中常见的简单请求:

    方法为:GET,HEAD,POST

    请求header里面:无自定义头

    Content-Type为以下几种:text/plain,multipart/form-data,application/x-www-form-urlencoded

    • 非简单请求:先发预options预检命令,通过后再发跨域请求

    res.addHeader("Access-Control-Allow-Headers", "Content-Type");//允许预检命令

    res.addHeader("Access-Control-Max-Age", "3600");//预检命令缓存秒数

    工作中常见的非简单请求:put,delete的请求,发送json格式的请求,带自定义头的请求


    三、带Cookie的跨域请求,response中需要设置

    res.addHeader("Access-Control-Allow-Credentials", "true");

    res.addHeader("Access-Control-Allow-Origin", "http://localhost:8081");//带Cookie时Access-Control-Allow-Origin需要全匹配,不能用通配符

    当多个域名都需要带Cookie跨域访问时,从Filter里面拿到Origin信息,把这个字段写入到Access-Control-Allow-Origin里面

    String origin = req.getHeader("Origin");

    if(!StringUtils.isEmpty(origin)) {

    res.addHeader("Access-Control-Allow-Origin", origin);

    }

    注意:1. 发送的Cookie是被调用方的Cookie,不是调用方的Cookie document.cookie="cookie1=xiaofengqing"这样就能新加入一个cookie了  2.Access-Control-Allow-Origin不能使用*


    四、带自定义头的跨域

    //支持所有自定义头

    String headers = req.getHeader("Access-Control-Request-Headers");

    if(!StringUtils.isEmpty(headers)) {

    res.addHeader("Access-Control-Allow-Headers",headers);

    }


  • 被调用方解决跨域问题,被调用方修改代码解决。

    调用方解决跨域,调用方修改Apache或者Nginx静态服务器,通过静态服务器隐藏调用请求返回给前台,前台以为是同一个地址和端口的请求就解决了跨域问题。

    02:53
    看视频
  • 一、http会话session依赖于cookie, sessionid存放在cookie中。

    二、ajax

    1、$.ajax({

        type: "get",

        xhrFields: {

            widthCredentials: true // 发送ajax请求的时候会带上cookie

        }

    })

    2、cookie是加在被调用方。

    <!--此处有图片-->

    服务端就是被调用方,而客户端就是调用方。在浏览器的控制台中通过document.cookie=""  来设置cookie。


    3、读cookie只能读到本域的。

    4、带cookie时,后台代码注意以下2点:

    (1)带cookie的时候,Access-Control-Allow-Origin,必须是全匹配,如http://localhost:8081, 不能是 *,否则报错,如下:

    <!--此处有图片-->


    (2)带cookie进行跨域时,需要设置以下请求头:

    res.addHeader("Access-Control-Allow-Credentials", "true")


    05:33
    看视频
  • 简单请求和非简单请求

    1.简单请求是先请求,浏览器再判断是否是跨域;而非简单请求要先发送一个预检命令,检查通过之后才会真正的把跨域请求发出去

    <!--此处有图片-->

    2.非简单请求常见的是发送json格式的请求,如图contentType为“application/json;charset=utf-8”<!--此处有图片-->

    最后的结果如下,返回了两个请求,一个是OPTIONS,另一个是POST请求,其中的OPTIONS就是一个预检命令,成功了之后才会发送后面的跨域请求

    <!--此处有图片-->

    3.预检命令的缓存。因为这种非简单请求每次都会发送两次请求,其实效率是比较低的,但是如果能缓存预检命令的话,会响应的提高效率

    在服务器中,添加一个响应头信息,告诉浏览器在截下来的一个小时可以缓存信息,就不需要再发送预检命令

    <!--此处有图片-->


    04:13
    看视频
  • 从服务端解决跨域问题:

    (1)被调用方解决跨域问题,被调用方修改代码解决。

    (2)调用方解决跨域,调用方修改Apache或者Nginx静态服务器,通过静态服务器隐藏调用请求返回给前台,前台以为是同一个地址和端口的请求就解决了跨域问题。


    一个请求是怎么被处理的:当一个请求从浏览器发出的时候,他会先到中间的http服务器或者叫静态服务器主要是由(apache/nginx)来处理的。中间的静态服务器收到请求后会判断是静态请求还是动态请求,和用户数据有关的就是动态请求,如图片,css,js就是静态请求,中间的静态服务器发现是静态请求时就会把请求直接处理,然后直接返回到客户端,如果是动态请求,请求从客户端发起到了中间的http服务器,中间的http服务器会把请求转发到后台的应用服务器处理完后再返回给中间的http服务器,http服务器再把请求转发到客户请求。

    02:47
    看视频
  • jsonp解决跨域问题的原理(区别):

    ①普通请求,发送请求时,请求类型type默认为 xhr  ;jsonp的请求类型为 script ,不会被浏览器认为是跨域异常;

    ②普通请求返回的数据类型默认为 json 格式;而 jsonp 的请求返回的数据类型为 javascript 的脚本;

    ③普通请求的地址后面没有携带任何数据;而jsonp请求的地址后面携带了 callback为键的一组键值对数据;由下列图片可知,

    当前端被设置为jsonp格式后,在后端中使用切面实现 jsonp 的格式化接口;该接口声明当返回的数据有callback这个值时,将返回的数据以jsonp的格式返回给前端,避免出现数据类型不一致的问题。


    00:38
    看视频
  • 我们知道非简单请求, 每次会发出两次请求, 这会影响性能. HTTP协议增加了个响应头, 可以让我们在服务端设置`Access-Control-Max-Age`来缓存预检请求, 比如说我们可以设置为3600m, 也就是一小时客户端只会在第一次的时候发送两个请求, 接下来一个小时内`OPTIONS`请求就被缓存起来了.

  • JSONP是一个非官方协议,它是一个约定,约定了一个请求的参数里如果包含指定的参数(默认是callback)这就是一个JSONP请求,服务发现是一个JSONP请求时就会把返回的值由原来的JSON对象改变JS代码,JS的代码的内容是函数调用的形式。他的函数名是callback参数的值,他的函数的参数是原来 要返回的JSON对象

  • 禁止浏览器跨域限制可通过传参数启动:解决Ajax跨域问题,调节浏览器的启动方式,--disable-web-security,即可解决,但是不推荐此方式。

  • Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

    为什么我们从不同的域(网站)访问数据需要一个特殊的技术(JSONP )呢?这是因为同源策略。

    同源策略,它是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。


    00:27
    看视频
首页上一页1234567下一页尾页

举报

0/150
提交
取消
课程须知
需要具备基本的前后台开发技术
老师告诉你能学到什么?
AJAX跨域产生的原因和解决思路 系统的基本部署架构和跨域的关系 http服务器nginx和apache的重要作用和跨域的2种解决思路 jsonp的工作机制和优缺点 前台测试框架Jasmine的使用

微信扫码,参与3人拼团

意见反馈 帮助中心 APP下载
官方微信
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!