zoukankan      html  css  js  c++  java
  • ajax跨域解决方案

    一、什么是AJAX? Asynchronous JavaScript and XML (Ajax ) 是驱动新一代 Web 站点(流行术语为 Web 2.0 站点)的关键技术。Ajax 允许在不干扰 Web 应用程序的显示和行为的情况下在后台进行数据检索。使用 XMLHttpRequest 函数获取数据,它是一种 API,允许客户端 JavaScript 通过 HTTP 连接到远程服务器。Ajax 也是许多 mashup 的驱动力,它可将来自多个地方的内容集成为单一 Web 应用程序。

    二、为什么会有这个问题? ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告。

    三、常见解决办法

    (1)使用script标签。 script调用没有域的限制,我们可以将输出的数据伪装成script的变量。

    (2)服务端脚本中转 服务端脚本使用XMLHTTP没有域的限制,但是耗费服务器的资源。

    (3)利用iframe 在同一个域名的各个子域名下,如果设置了document.domain,那么是可以相互调用JS的。

    (4)JSONP 这个方法也是最解决正常AJAX和多人使用的。 JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。 首先在客户端注册一个callback, 然后把callback的名字传给服务器。 此时,服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp. 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。 客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)。

    (5)CORS CORS-CrossOrigin Resources Sharing,也即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的。

    但是CORS也具有一定的风险性,比如请求中只能说明来自于一个特定的域但不能验证是否可信,而且也容易被第三方入侵。

    nginx增加类似如下配置:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. server {  
    2.     location / {  
    3.         if ($request_method = 'OPTIONS') {  
    4.           add_header 'Access-Control-Allow-Origin' '*';  
    5.           add_header 'Access-Control-Allow-Credentials' 'true';  
    6.           add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  
    7.           add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';  
    8.          # add_header 'Access-Control-Max-Age' 1728000;  
    9.           add_header 'Content-Type' 'text/plain charset=UTF-8';  
    10.           add_header 'Content-Length' 0;  
    11.           return 200;  
    12.         }  
    13. }  

    如果没有nginx转发,java需要如下代码: 

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
      1. rundata.getResponse().addHeader("Access-Control-Allow-Origin", "*");  
      2. rundata.getResponse().addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");  
      3. rundata.getResponse().addHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");  

    Tomcat下的配置 下载cors-filter-1.7.jar,java-property-utils-1.9.jar这两个库文件,放到lib目录下。(可在 http://search.maven.org上查询并下载。)工程项目中web.xml中的配置如下: 

     

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <filter>  
    2.     <filter-name>CORS</filter-name>  
    3.     <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>  
    4.     <init-param>  
    5.      <param-name>cors.allowOrigin</param-name>  
    6.         <param-value>*</param-value>  
    7.     </init-param>  
    8.     <init-param>  
    9.      <param-name>cors.supportedMethods</param-name>  
    10.         <param-value>GET, POST, HEAD, PUT, DELETE</param-value>  
    11.     </init-param>  
    12.     <init-param>  
    13.      <param-name>cors.supportedHeaders</param-name>  
    14.         <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>  
    15.     </init-param>  
    16.     <init-param>  
    17.         <param-name>cors.exposedHeaders</param-name>  
    18.         <param-value>Set-Cookie</param-value>  
    19.     </init-param>  
    20.     <init-param>  
    21.         <param-name>cors.supportsCredentials</param-name>  
    22.         <param-value>true</param-value>  
    23.     </init-param>  
    24. </filter>  
    25. <filter-mapping>  
    26.     <filter-name>CORS</filter-name>  
    27.     <url-pattern>/*</url-pattern>  
    28. </filter-mapping>  

     

     

    假设我们页面或者应用已在 http://www.test1.com 上了,而我们打算从 http://www.test2.com 请求提取数据。一般情况下,如果我们直接使用 AJAX 来请求将会失败,浏览器也会返回“源不匹配”的错误,"跨域"也就以此由来。
      利用 CORS,http://www.test2.com 只需添加一个标头,就可以允许来自 http://www.test1.com 的请求,下图是我在PHP中的 hander() 设置,“*”号表示允许任何域向我们的服务端提交请求
         

      也可以设置指定的域名,如域名 http://www.test2.com ,那么就允许来自这个域名的请求

         

     

    1.第一步 设置响应头

    header('Access-Control-Allow-Origin:*');  //支持全域名访问,不安全,部署后需要固定限制为客户端网址

    header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http 动作

    header('Access-Control-Allow-Headers:x-requested-with,content-type');  //响应头 请按照自己需求添加。

    2.第二部 了解IE chrome 等浏览器 对于 跨域请求并要求设置Headers自定义参数的时候的 "预请求"   就是如果遇到 跨域并设置headers的请求,所有请求需要两步完成!

    A 第一步:发送预请求 OPTIONS 请求。此时 服务器端需要对于OPTIONS请求作出响应 一般使用202响应即可 不用返回任何内容信息。(能看到这份手稿的人,本人不相信你后台处理不了一个options请求)

    B 第二步:服务器accepted 第一步请求后 浏览器自动执行第二步 发送真正的请求。此时 大多数人 会发现请求成功了,但是 有那么几个人会发现 请求成功了但是没有任何信息返回 why?因为你自定义的请求头在服务器响应中不存在!

    查看console输出 会发现一个问题:

    “Access-Control-Allow-Headers 列表中不存在请求标头 XXXXXX”【IE】,

    request header field xxxxxx is not allowed by Access-Control-Allow-Header【chrome】

    这是因为 你的XXXX请求头 没有在服务器端被允许哦~

    遇到这个问题 只有通过修改服务器端来完成,举例:需要设置 requesttype这么一个自定义头,那么 你需要在 服务端里面 将header('Access-Control-Allow-Headers:x-requested-with,content-type,requesttype');  同学们自行体会吧 这种语法就是根据“,”分割 自己需要设置什么头,必须要在 服务端请求的响应头里面设置好,不然客户端永远永远提交不上去!

    至此  JavaScript/ajax  跨域+ 修改httpheader 任务完美实现。前端 后端完全分离 大道自成!前后期分离迎来旷古的潮流

     次处作为见证 2016年1月25日20:21:28

    "人们都一直在抱怨 JavaScript同源策略限制了web前端的发展!然而是服务端做的不够细致!"

    部分代码参考如下:代码只是提供了思想,具体步骤还要根据以上的文字 自行揣摩实现。以上内容看不懂 说明对于web一点也不了解,需要买本书看看喽~(本人个人经历成功实现。若有人遇到同样的问题可以 加群245961308)

    客户端代码:

     

    服务器端代码

  • 相关阅读:
    POJ 1095 Trees Made to Order 最详细的解题报告
    Producter and Consumer
    How to use the function of bind
    How to use the functions of apply and call
    Configurate vim tool
    #4713. 方程
    #4709. 树
    #4718. 管理
    #4710. 并
    #4707. 点分治
  • 原文地址:https://www.cnblogs.com/sprinng/p/5216126.html
Copyright © 2011-2022 走看看