跨域访问-ajax

ajax跨域访问方案分为jsonp和cors,本文将会对两种方案进行介绍。

jsonp

jsonp的原理是利用html文档script标签可以跨域访问的特点,通过在HTML文档中动态添加script标签,从其它域获取数据并在原HTML文档中回调处理数据。下面利用jquery封装好的jsonp,跨域获取数据。

清单:www.a.com的html文档

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>AJAX Tester</title>
    <script type="text/javascript" src="js/jquery.js"></script>

    <script type="text/javascript">
        $(function () {
            // jsonp形式的请求
            $.ajax({
                url: "http://www.b.com/user_info?callback=?",
                data: {id: 1},
                dataType: "jsonp"
            }).done(showResult);
        });

        function showResult(ret) {
            console.log(ret);
            $("#container").html(ret.name);
        }
    </script>

</head>
<body>
My name is:
<span style="font-weight:bold;" id="container"></span>

<script type="text/javascript">

</script>

</body>
</html>

代码中,采用ajax jsonp的方式请求www.b.com域名获取数据,并显示在页面中。 JSONP默认采取get方式请求数据。

清单:www.b.com的API

@WebServlet("/user_info")
public class GetUserInfoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        // 要正确设置响应类型,避免IE出现下载
        response.setContentType("application/javascript");

        String userInfo = "{\"id\":1, \"name\":\"zhangsan\"}";

        String ret;

        // 通过参数传递回调函数名,一定程度降低了前后端代码的耦合度
        String callback = request.getParameter("callback");
        if (callback != null && !callback.isEmpty()) {
            ret = callback + "(" + userInfo + ")"; //拼接jsonp字符串
        } else {
            ret = userInfo; //正常返回json数据
        }

        response.getWriter().write(ret);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

JSONP的返回数据的格式是 callback_method(json_data) ,这里的callback_method对应于原html文档中存在的一个函数的函数名。

缺点: jsonp采用的是get方法请求数据,当数据量很大的时候,不能解决跨域请求数据的问题。

CORS

CORS,全称跨域资源共享(Cross-Origin Resource Sharing)。CORS 是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源。

既然CORS是一种规范,那么必须需要浏览器实现这种规范,这就不可避免出现浏览器兼容的问题。我们看一下各浏览器对CORS的支持


CORS请求又分为简单请求和非简单请求。简单请求是指通过GET方式获取资源;非简单请求是指 如POST、PUT、DELETE类型请求,或者在请求中有其它自定义的HTTP Header。下面详细介绍一下对于不同的请求的实现方法。

简单请求

response中需要添加Access-Control-Allow-Origin头,告诉浏览器哪些域名的网站可以获取返回的数据

response.addHeader("Access-Control-Allow-Origin", "*"); //可以跨域访问的域名

清单:www.a.com的html文档获取www.b.com的数据

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>AJAX Tester</title>
    <script type="text/javascript" src="js/jquery.js"></script>

    <script type="text/javascript">
        $(function () {
            $.ajax({
                url: "http://www.b.com/user_info_2",
                method: "GET"
            }).done(showResult);

        });

        function showResult(ret) {
            $("#container").html(ret.name);
        }
    </script>

</head>
<body>
My name is:
<span style="font-weight:bold;" id="container"></span>

</body>
</html>

清单:www.b.com通过cors方式返回数据给www.a.com

@WebServlet("/user_info_2")
public class GetUserInfoServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        // 简单请求,直接设置Access-Control-Allow-Origin就可以了
        response.addHeader("Access-Control-Allow-Origin", "*"); //可以跨域访问的域名

        // 要正确设置响应类型,避免IE出现下载
        response.setContentType("application/json");

        response.getWriter().write("{\"id\":1, \"name\":\"zhangsan\"}");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

非简单请求

对于非简单请求,会执行一次preflight操作,浏览器会发起一次OPTIONS类型请求,要对OPTIONS请求给予正确应答,应答内容是允许谁访问,允许什么方法,允许什么自定义头的request。下面看一下一次request请求的CORS流程。

打开调试模式后,可以看到一次request请求被分成了两次:
第一个请求是用OPTIONS方法。 //这里所做是的是预检查,从服务器确认是否可以继续
第二个请求才是你发起的请求方法。

清单:www.a.com的html文档,对www.b.com发起ajax请求数据,并携带了自定义 HEADER和采用POST方法

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>AJAX Tester</title>
    <script type="text/javascript" src="js/jquery.js"></script>

    <script type="text/javascript">
            $.ajax({
                url: "http://www.b.com/user_info_2",
                method: "POST",
                beforeSend: function (xhr) {
                    //添加自定义头
                    console.log("before send");
                    xhr.setRequestHeader("myheader", "abc")
                }
            }).done(showResult);

        });

        function showResult(ret) {
            $("#container").html(ret.name);
        }
    </script>

</head>
<body>
My name is:
<span style="font-weight:bold;" id="container"></span>

</body>
</html>

清单:www.b.com的API在option的处理中,对response添加了一些头。

@WebServlet("/user_info_2")
public class GetUserInfoServlet2 extends HttpServlet {
    @Override
    protected void doOptions(HttpServletRequest request,
                             HttpServletResponse response) throws ServletException, IOException {
        System.out.println("OPTIONS");
        response.addHeader("Access-Control-Allow-Origin", "*");

        response.addHeader("Access-Control-Allow-Methods",
                "GET, POST, OPTIONS, DELETE");
        response.addHeader("Access-Control-Allow-Headers", "myheader, myheader2");
    }

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {

        // 要正确设置响应类型,避免IE出现下载
        response.setContentType("application/json");

        response.getWriter().write("{\"id\":1, \"name\":\"zhangsan\"}");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

大家可以看到利用CORS方案处理ajax跨域请求的问题,但是比较麻烦的是需要修改java代码,侵入性很强。为了解决这个问题,我们可以在nginx中配置,让response返回的时候自动添加返回头。

niginx的配置如下:

  if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
             }
             if ($request_method = 'POST') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
             }
             if ($request_method = 'GET') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
             }

原文链接

时间: 2024-07-28 13:22:42

跨域访问-ajax的相关文章

ajax跨域访问-ajax的跨域访问快递接口

问题描述 ajax的跨域访问快递接口 访问一个快递查询接口:html如下: <!DOCTYPE html><html><head><meta charset=""UTF-8""><title>Insert title here</title><script type=""text/javascript"" src=""js/jqu

支持Ajax跨域访问ASP.NET Web Api 2(Cors)的示例教程_实用技巧

随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Angularjs的框架来做UI,而数据则由另一个Web Api 的网站项目来支撑.注意,这里是两个Web网站项目了,前端项目主要负责界面的呈现和一些前端的相应业务逻辑处理,而Web Api则负责提供数据. 这样问题就来了,如果前端通过ajax访问Web Api项目话,就涉及到跨域了.我们知道,如果直接访问,正常情况下Web Api是不允许这样做的,这涉及到安全问题.所以,今天我们这篇文章的主

浅析JSONP解决Ajax跨域访问问题的思路详解_AJAX相关

前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现方法有多种,本例采用jQuery+Ajax,完成后,在本地调试了一切ok,但是部署到服务器上以后就出现问题了,后台服务调用没有响应,怎么回事?代码没怎么改动,唯一修改的地方就是jQuery的ajax方法中的url地址.难道是这里的问题,经过检查和调试,发现原来是同源策略在作怪,我们知道,JavaScript或jQuery是在Web前端开发中经常使用的动态脚本技术.在JavaScript中,有一个很重要

AJax与Jsonp跨域访问问题小结_AJAX相关

####JavaScript的AJax AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML) 设计AJax使用的一种重要技术是XMLHttpRequest对象. 创建XMLHttpRequest对象的方式: xmlhttp = new ActiveObject("Microsoft.XMLHTTP"); // IE浏览器支持的创建方式 xmlhttp = new XMLHTTPRequest(); // F

浅谈JQuery+ajax+jsonp 跨域访问_jquery

Jsonp(JSON with Padding)是资料格式 json 的一种"使用模式",可以让网页从别的网域获取资料. 一. 客户端 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=&q

ajax跨域访问报错501的解决方法_AJAX相关

问题:ajax跨域访问报错501 运行下面的代码会报错501 $.ajax({ type: "POST", url: "http://192.168.1.202/sensordata.php", contentType:'application/json; charset=utf-8', data: JSON.stringify(ajaxPostData), dataType:'json', success: function(data){ //On ajax su

Web安全技术之浏览器的跨域访问

 一.浏览器介绍 对于Web应用来说,浏览器是最重要的客户端. 目前浏览器五花八门多得不得了,除了Chrome.IE.Firefox.Safari.Opera这些国外的浏览器外,百度.腾讯.360.淘宝.搜狗.傲游之类的,反正能做的都做了. 浏览器虽然这么多,但浏览器内核主要就以下4种: Trident:IE使用的内核. Gecko:Firefox使用的内核. WebKit:Safair和Chrome使用的内核.WebKit由苹果发明,Chrome也用了,但是Google又开发了V8引擎替换掉了

Ajax实现跨域访问的三种方法

本文给大家介绍了ajax实现跨域访问的3种解决方案,非常的实用,个人比较推荐第三种,小伙伴们可以着重看下.     一.什么是跨域 我们先回顾一下域名地址的组成: http:// www . google : 8080 / script/jquery.js http:// (协议号) www (子域名) google (主域名) 8080 (端口号) script/jquery.js (请求的地址) * 当协议.子域名.主域名.端口号中任意一各不相同时,都算不同的"域". * 不同的域

Ajax实现跨域访问的三种方法_AJAX相关

一.什么是跨域 我们先回顾一下域名地址的组成: http:// www . google : 8080 / script/jquery.js   http:// (协议号)                www  (子域名)              google (主域名)                8080 (端口号) script/jquery.js (请求的地址) * 当协议.子域名.主域名.端口号中任意一各不相同时,都算不同的"域". * 不同的域之间相互请求资源,就叫&