加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

AJAX跨域访问

发布时间:2020-12-15 21:38:08 所属栏目:百科 来源:网络整理
导读:谈到 js 跨域访问,首先要了解的一个概念,就是同源策略。所谓同源是指域名、协议、端口相同。不同源的客户端脚本( javascript 、 ActionScritp )在没明确授权的情况下,不能读写对方的资源。简单的来说,就是浏览器仅允许包含在 A 页面的脚本访问与他同域

谈到js跨域访问,首先要了解的一个概念,就是同源策略。所谓同源是指域名、协议、端口相同。不同源的客户端脚本(javascriptActionScritp)在没明确授权的情况下,不能读写对方的资源。简单的来说,就是浏览器仅允许包含在A页面的脚本访问与他同域名下的页面或者服务器资源(如serviceactionservletjs脚本等),不同域名下的脚本不能互相访问,即便是子域也不行。它是由Netscapte提出的一个著名的安全策略,现在所有的支持JavaScript的浏览器都会使用这个策略。

如果我们需要不同域名下的脚本互相访问的话,由于同源策略的限制,直接访问肯定不行。这样,就涉及到了跨域访问的问题。如何解决跨域访问问题呢?这里提供三个方案。

  • 采用JSONP跨域GET请求是一个常用的解决方案。
  • 用服务端的XmlHttpRequest代理实现跨域访问
  • 基于iframe(一般用于父域子域之间的跨域)

JSONP方式实现跨域请求

JSONP工作原理:由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。若要跨域请求出于安全性的考虑是不行的。但是我们发现,Web页面上调用js文件时则不受是否跨域的影响,而且拥有“src”这个属性的标签都具有跨域的能力,比如<script><img><iframe>。如果通过使用htmlscript标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。即在跨域的服务端生成JSON数据,然后包装成script脚本回传,就突破了同源策略的限制,解决了跨域访问的问题。

JSONP的缺点:JSONP不提供错误处理。如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。demo1

客户端代码

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8" />
      <title>客户端</title>
      <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
      <script type="text/javascript">
         function SendData(){
            $.ajax({
                type:"get",url:"http://127.0.0.1:8080/WebTest/doTestServer",dataType:"jsonp",jsonp:"callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名
                //的参数名(一般默认为callback)不需要改动
                jsonpCallback:"clientreceive",//自定义的jsonp回调函数名称,
                //默认为jQuery自动生成的随机函数名,也可以写“?”,jQuery会自动为你处理数据
                //执行成功后执行的方法,此方法在clientreceive方法之后执行
                success:function(data){
                   alert(data.name);
                },error:function(data){
                   alert("出错了!");
                }
            });
         }
         //将服务端返回的数据封装成相应的js文件
         functionclientreceive(data){
            alert(data.age);
         }
      </script>
   </head>
   <body>
      <input type="button" value="提交" onclick="SendData();"/>
   </body>
</html>

服务端代码:(此demo服务端用servlet实现)

public class testService extends HttpServlet{
   @Override
   protectedvoiddoGet(HttpServletRequest req,HttpServletResponse resp)
         throws ServletException,IOException {
      resp.setContentType("application/json;charset=utf-8");
      Stringcallback = req.getParameter("callback");
      Stringjson = " ({'name':'张三','age':'20'})";
      resp.getWriter().write(callback+ json);//注意此处输出的数据格式
   }

}


用服务端的XmlHttpRequest代理实现跨域访问

我们不能在浏览器端直接使用AJAx来跨域访问资源,但是在服务端是没有这种跨域安全限制的。所以,我们只需要让服务器端帮我们完成“跨域访问”的工作,然后在浏览器端用AJAX获取服务端“跨域访问”的结果就可以了。

客户端js代码

<span style="font-size:14px;">function SendData(){
            $.ajax({
                type:"get",url:"doServiceProxy",success:function(res){
                   varsubval=res.substring(res.indexOf("(")); //返回的参数名
                   varcallfunc=res.substring(0,res.indexOf("(")); //返回的数值
                   var json = (new Function("return "+ subval))(); //转换为json格式
                   if($.trim(callfunc)=='clientreceive'){
                      clientreceive(json);//调用回调方法,将返回的数值封装成相应的文件
                   }
                   alert(json.name);
                   alert(json.age);   
                },error:function(res){
                   alert("失败");
                }
            });
         }
          //将服务端返回的数据封装成相应的js文件
         functionclientreceive(data){
            alert("处理服务端数据");
         }
</span>

本地服务端代码(跨域代理)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
@SuppressWarnings("deprecation")
publicclassserviceproxy extends HttpServlet{
   privatestaticfinallongserialVersionUID= -2007067084377015151L;
   @Override
   protectedvoiddoGet(HttpServletRequest req,IOException {
      HttpClientclient=newDefaultHttpClient();  
      HttpGethttpgets=newHttpGet("http://127.0.0.1:8080/WebTest/doTestServer?callback=clientreceive");
      HttpResponseresponse=client.execute(httpgets);
      HttpEntityentity=response.getEntity();
      if(entity!=null){
         InputStreaminstreams=entity.getContent();
         Stringstr=convertStreamToString(instreams);
         resp.getWriter().write(str);
      }
   }
   //将流转换为字符串
   publicstatic StringconvertStreamToString(InputStream is){
      BufferedReaderreader=newBufferedReader(newInputStreamReader(is));
      StringBuildersb=newStringBuilder();
      Stringline=null;
      try{
         while((line=reader.readLine())!=null){
            sb.append(line+"n");
         }
      }catch(Exception e){
         e.printStackTrace();
      }finally{
         try{
            is.close();
         }catch(Exception e){
            e.printStackTrace();
         }
      }
      return sb.toString();
   }
   @Override
   protectedvoiddoPost(HttpServletRequest req,HttpServletResponse resp)

         throws ServletException,IOException {
      doGet(req,resp);
   }
}

远程服务端(最终要访问的跨域服务端)与demo1服务端代码一致。

基于iframe实现跨域访问demo(一般用于父域子域之间的跨域)

基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com或是xxx.com.cn),使用同一协议(例如都是http)和同一端口,这样在两个页面中同时添加document.domain,就可以实现父页面调用子页面的函数。

页面一:

<html> 
<head> 
 <script>  
  document.domain = "xx.com"; 
   function aa(){  
     alert("p");  
  }  
 </script>  
</head> 

<body> 
  <iframe src="http://localhost:8080/CmsUI/2.html"id="i">  
  
  </iframe>  
  <script>  
    document.getElementById('i').onload = function(){  
      var d = document.getElementById('i').contentWindow;  
      d.a();  
       
    };  
  </script>  
 </body> 
</html> 

页面2

<html> 
 <head> 
 <script>  
   document.domain = "xx.com"; 
   function a(){  
     alert("c");  
   }  
 </script>  
 </head> 
 <body> 
 </body> 
</html> 

参考资料:http://www.52php.cn/article/p-ssnpnhce-sq.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读