博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
跨域访问-ajax
阅读量:6422 次
发布时间:2019-06-23

本文共 5433 字,大约阅读时间需要 18 分钟。

hot3.png

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

jsonp

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

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

    
AJAX Tester My name is:

代码中,采用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的数据

    
AJAX Tester My name is:

清单: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方法

    
AJAX Tester My name is:

清单: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';             }

转载于:https://my.oschina.net/thinwonton/blog/1055826

你可能感兴趣的文章
js生成二维码
查看>>
C指针练习
查看>>
web项目buildPath与lib的区别
查看>>
php对redis的set(集合)操作
查看>>
我的友情链接
查看>>
ifconfig:command not found的解决方法
查看>>
计算机是怎么存储数字的
查看>>
Codeforces Round #369 (Div. 2) A. Bus to Udayland 水题
查看>>
adb上使用cp/mv命令的替代方法(failed on '***' - Cross-device link解决方法)
查看>>
C++标准库简介、与STL的关系。
查看>>
Spring Boot 3 Hibernate
查看>>
查询EBS请求日志的位置和名称
查看>>
大型机、小型机、x86服务器的区别
查看>>
J2EE十三个规范小结
查看>>
算法(第四版)C#题解——2.1
查看>>
网关支付、银联代扣通道、快捷支付、银行卡支付分别是怎么样进行支付的?...
查看>>
大数据开发实战:Stream SQL实时开发一
查看>>
C++返回引用的函数例程
查看>>
dll 问题 (转)
查看>>
REST API用得也痛苦
查看>>