Ajax跨域问题

一、跨域问题

1、浏览器控制台出现以下错误,说明是ajax跨域问题
       No 'Access-Control-Allow-Origin' header is present on the requested resource.

二、跨域的定义以及产生原因

● 什么是跨域?
     说到跨域,就必须知道同源策略,它是一种安全策略,所谓的同源是指域名、协议、端口号 相同。
  一个域名的网页去请求另一个域名的资源,即发出去的请求不是本域的请求,不符合同源策略,就造成了
  跨域。

● 产生跨域的原因

1、浏览器的限制:
          浏览器出于安全考虑,当发现请求时跨域的,就会进行校验,如果校验不通过,就会出现跨域
       安全问题

2、请求是跨域的:
          发出去的请求不是本域的请求,请求里面协议、域名、端口任何一个不一样,浏览器就认为
       是跨域的

3、请求的类型是XHR(XMLHttpRequest)请求:
          发出去的请求的必须是XHR类型(type),如果不是这个类型,则浏览器不会报跨域错误

  ★ 总结:产生跨域的原因有3个,这三个原因必须同时满足,才会发生浏览器跨域问题

三、解决思路

1、解决浏览器的限制:
           可以通过浏览器指定参数,让浏览器不去做这个校验,这个跨域问题就解决了,但是这种方法价值不大,因为需要每个人都在客户端进行改动

2、改变XHR请求类型
         只要发出去的请求类型不是XHR类型的,就算是跨域的,浏览器控制台也不会报跨域安全问题

     ★   基于这种思路,我们的解决方案是 :JSONP,它通过动态创建Script,在Script中发出跨域请求,
                                      但是JSONP的解决方案有很多弊端,无法满足现在开发的要求,所以现在使用的人越来越少了

3、跨域
         所以解决跨域问题,重点放在怎么解决跨域,两种思路:
         ①、被调用方支持跨域
                 比如:A域名 调用 B域名,只要给B域名返回的信息中加入一些字段,告诉浏览器我允许A域名的调用,只要浏览器通过校验,
                      就不会出现跨域问题

         ②、调用方隐藏跨域
                        通过一个代理,从浏览器发出去的都是A域名的请求,在代理里面把指定的URL转到B域名中,这样在浏览器看来就是同
                    一个域名,就没有跨域问题,所以跨域问题就解决了

四、JSONP

1、JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

2、使用JSONP,发送的请求类型是script;返回的类型是js脚本(javaScript);JSONP的URL后面加了一个callback参数,
   服务器把返回的内容由JSON变为JavaScript,JavaScript的内容就是一个函数调用

3、JSONP的缺点:
    ①、它只支持GET请求而不支持POST等其它类型的HTTP请求;
    ②、它发送的请求类型不是XHR类型
    ③、服务器需要改动代码支持

4、实现原理
     JSONP是一个非官方协议,是一个前后台的约定,约定发送请求的参数中如果包含指定的参数,
  默认为callback,那么就是一个JSONP请求, 服务器发现是一个JSONP请求,就把返回的数据由
  原来的JSON对象改为一个JS函数调用的形式,callback的值作为函数名,原来返回的JSON对象作
  为函数的参数返回。
JavaEE架构.png

五、跨域解决的方向

▲ 普通请求和跨域请求的区别是:跨域请求的请求头中会有一个Origin字段,这个字段的值是当前域名的信息,当浏览器发现这个请求是跨域的时候,
  就会在请求头添加一个Origin字段,然后等请求返回的时候,就会检查响应头中是否有允许跨域的信息,如果没有,就会报错。

1、被调用方解决
       被调用方解决支持跨域,主要是添加响应头字段,告诉浏览器支持跨域调用,有三种方法:
       
       ①、服务端实现(重点)
               简单请求是先执行,后判断,非简单请求是先发一个OPTIONS预检命令,如果检查通过,才会真正把跨域请求发送出去

              工作中比较常见的[简单请求]:
                    Methods: GET, HEAD, POST

                    请求 header 里面:
                            * 无自定义头

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

               工作中常见的[非简单请求]:

                            * put, Delete 方法的 ajax 请求

                            * 发送JSON格式的 ajax 请求

                            * 带自定义头的 ajax 请求
              
          ● 被调用方解决方案:filter解决
                 创建一个filter,在filter的doFilter方法中添加如下响应头字段:
                   response.addHeader("Access-Control-Allow-Origin", "*");  //允许这个域跨域调用
                   response.addHeader("Access-Control-Allow-Methods", "*");  //指定允许的方法 
                   response.addHeader("Access-Control-Allow-Headers", "Content-Type");  //告诉浏览器允许这个Header  
                   response.addHeader("Access-Control-Max-Age", "3600");  //告诉浏览器允许在指定时间(秒)缓冲信息,不需要再发送预检命令  

             ▲  带Cookie的跨域:
                     (1)、Cookie要加再被调用方;
                     (2)、浏览器发现是跨域的时候,会在请求头中添加Oragin字段,该字段中包含了当前域的信息
                     (3)、要想支持所有域的跨域请求,就需要在request中取出Oragin字段,然后判断该字段不为空时,把该字段设置到     
                          response.addHeader("Access-Control-Allow-Origin", oragin);  //调用方的URL

                   在Filter中添加如下,Origin参数为 * 时,是不能满足带Cookie的跨域请求的,必须全匹配
                   response.addHeader("Access-Control-Allow-Origin", "http://localhost:8081");  //调用方的URL
                   response.addHeader("Access-Control-Allow-Credentials", "true");  //允许Cookie
Ajax携带Cookie.png
             ▲  带自定义头的跨域:

添加自定义头的两种方式.png
支持所有自定义头.png
       ②、NGINX配置 【重点】

          ● 被调用方解决方案:Nginx解决

       ③、Spring框架解决方案 【重点】
                  只需要添加 @CrossOrigin注解,可以加在类上面(表示这个类上的所有方法都支持跨域),也可以加在方法上面

       ④、APACHE配置

2、调用方解决方案(隐藏跨域)
              跨域请求通过调用方的Http服务器的反向代理转发到被调用方的服务器,在浏览器看来,都是同一域名

       ①、NGINX配置(反向代理)  【重点】

          ● 调用方解决方案:Nginx解决

       ②、APACHE配置

          ● 调用方解决方案:APACHE解决

隐藏跨域和支持跨域最大的不同是,隐藏跨域调用的URL都是本域的,使用的是相对地址,而支持跨域使用的是绝对地址

五、浏览器禁止检查

命令行参数启动浏览器,输入:
           chrome --disable-web-security --user-data-dir=g:\temp3
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容