聊聊Ajax跨域

前言 

  由于浏览器的同源策略,使得发送请求的时候,只能给本域发送请求,不能跨域发送请求。对于Ajax请求来说,跨域浏览器是不允许的。原因不是不能发送,Ajax跨域的时候,确实发送了请求,并且收到了另一个域名的响应。但是浏览器会报错,默认情况下,Ajax不允许跨域,而script,img,  iframe 允许跨域,  基本上通过src引用去发送请求的,都可以跨域。src请求相当于发送了一个GET请求

  那么如何让Ajax可以跨域请求呢?今天介绍两种方案

JSONP

  什么是jsonp?jsonp是如何实现跨域请求的呢?

  在前言中提到,对于Ajax提交的请求是不允许跨域,只能是本域请求,而浏览器允许具有src属性的元素跨域进行请求。那么是否可以借助src属性来帮助Ajax跨域呢?

  答对了,这就是jsonp实现跨域请求的基本原理

  优点:兼容性好,应用广泛

  缺点:由于是src引用发送的请求,那么jsonp的请求只能是get请求,不能是其他的请求。

  好了,说到这里,我们来看看,jsonp是如何跨域的

 1 # Python write by yhy
 2 import tornado.web
 3 import tornado.ioloop
 4
 5 class IndexHandler(tornado.web.RequestHandler):
 6     def get(self, *args, **kwargs):
 7         self.write(‘func([11,22,33])‘)
 8
 9 # 说明一下这个‘static_url_prefix‘: ‘/statics/‘,的问题
10 settings = {
11     ‘template_path‘: ‘views‘,
12     ‘static_path‘: ‘statics‘,
13     ‘static_url_prefix‘: ‘/statics/‘,
14 }
15
16 application = tornado.web.Application([
17     (r‘/index‘, IndexHandler)
18 ], **settings)
19
20 if __name__ == ‘__main__‘:
21     application.listen(8002)
22     tornado.ioloop.IOLoop.instance().start()

服务端tornado框架代码

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <script src="/statics/jquery.js"></script>
 7 </head>
 8 <body>
 9 <input type="button" value="Ajax" onclick="DoAjax();">
10 <input type="button" value="JsonpAjax" onclick="DoJsonpAjax();">
11 <script>
12     function func(arg) {
13         console.log(arg)
14     }
15
16     // Ajax
17     function DoAjax() {
18         $.ajax({
19             url: ‘http://127.0.0.1:8002/index‘,
20             type: ‘POST‘,
21             data: {‘k1‘: ‘v1‘},
22             success: function (arg) {
23                 console.log(arg);
24             }
25         })
26     }
27
28     // JsonAjax
29     function DoJsonpAjax() {
30         var tag = document.createElement(‘script‘);
31         tag.src = "http://127.0.0.1:8002/index";
32         document.head.appendChild(tag);
33         document.head.removeChild(tag);
34     }
35 </script>
36 </body>
37 </html>

原生的AjaxJSONP

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <script src="/statics/jquery.js"></script>
 7 </head>
 8 <body>
 9 <input type="button" value="Ajax" onclick="DoAjax();">
10 <input type="button" value="JsonpAjax" onclick="DoJsonpAjax();">
11 <script>
12     // 这里的func函数就是等待被调用,等待跨域请求返回的调用函数的字符串调用,一旦调用就会在这个函数中拿到跨域请求的参数。
13     function func(arg) {
14         console.log(arg)
15     }
16
17     // Ajax
18     function DoAjax() {
19         $.ajax({
20             url: ‘http://127.0.0.1:8002/index‘,
21             type: ‘POST‘,
22             data: {‘k1‘: ‘v1‘},
23             success: function (arg) {
24                 console.log(arg);
25             }
26         })
27     }
28
29     // JsonAjax
30     function DoJsonpAjax() {
31         // 基于jquery的Ajax的跨域请求,只要指明dataType为‘jsonp‘,那么就相当于创建了一个带有src的script标签,跨域请求通常返回一个函数,这个函数包裹在<script> func(‘hello world’) <script> 标签里面。一旦返回到html页面的时候,将会调用提前在<script> <script> 标签中写好的函数。这个写好的<script> <script>标签中写好的函数就会拿到函数调用传递进来的参数‘hello world’。这样就实现了跨域的请求
32         $.ajax({
33             url: ‘http://127.0.0.1:8002/index‘,
34             dataType: ‘jsonp‘,
35             jsonpCallBack: ‘func‘
36
37         })
38     }
39 </script>
40 </body>
41 </html>

基于jQuery的AjaxJSONP

  ** 思考:服务端的返回的func函数名称是否可以与客户端提前写好的回调函数名一致呢,如果一致的话,那么就不需要在服务端指定函数名了,客户端的回调函数叫什么名字,服务端就叫什么名字就好。

  解决的方式:服务端拿到请求的url的参数,这个参数里面有一个callback参数,这个callback参数的值就是客户端请求的函数名称

  那么服务端返回的代码就可以这么写:通过self.get_argument(‘callback‘)拿到客户端的回调函数名

服务端拿到返回的函数名

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6
 7     <script src="../statics/jquery.js"></script>
 8 </head>
 9 <body>
10 <input type="button" onclick="AjaxJsonp();" value="Ajax" >
11 <input type="button" onclick="jQueryAjaxJsonp();" value="jqueryAjax">
12
13 <script>
14     function getData(arg) {
15         console.log(arg);
16     }
17     function AjaxJsonp() {
18         var tag = document.createElement(‘script‘);
19         tag.src = ‘http://yhycn.com:8002/index?callback=getData‘;
20         document.head.appendChild(tag);
21         document.head.removeChild(tag);
22     }
23     function jQueryAjaxJsonp() {
24         $.ajax({
25             url: ‘http://yhycn.com:8002/index‘,
26             dataType: ‘jsonp‘,
27             // 下面的jsonp: ‘callback‘,jsonCallBack: ‘getData‘, 相当于在请求的url中指定/index?callback=getData
28             jsonp: ‘callback‘,
29             jsonCallback: ‘getData‘,
30         })
31     }
32 </script>
33 </body>
34 </html>

前端html代码

CORS:跨域资源共享(Cross-Origin Resource Sharing)

  当客户端跨域请求时,服务端返回数据的时候,同时绑定一个标记,告诉浏览器这是跨域请求的数据,不要报错。当浏览器识别这个标示的时候,浏览器就不会报错了,这个表示就是加上一个响应头CORS。这样就实现了跨域请求。客户端请求与本域请求一样不变,服务端这是一个CORS响应头即可。

  优点:客户端不需要修改原本的ajax跨域请求,只是服务端需要进行相应的设置即可

  缺点:兼容性不好,由于IE浏览器对跨域资源共享的兼容性问题,因此cors应用不是很广泛

  概念说明:

条件:

    1、请求方式:HEAD、GET、POST

    2、请求头信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID

        Content-Type 对应的值是以下三个中的任意一个
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain

注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求

1:简单的cors请求

对应简单的cors请求而言,与普通的本域请求一样,而服务端需要在set-header中设置运行的请求客户端地址

2:复杂的cors请求

对应复杂的cors请求而言,与普通的本域请求不一样的地方在于,请求方法可以是head, get , post之外的其他方法,可以自定义请求头,可以告诉客户端浏览器请求的时候携带cookie。客户端会先发送一个options自检请求,在发送一个type中指定的请求

而服务端对复杂的cors请求,首先会处理自检请求,在处理type中指定的请求

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <script src="/statics/jquery.js"></script>
 7 </head>
 8 <body>
 9
10 <input type="button" onclick="jQueryAjax();" value="jqueryAjax">
11 <input type="button" onclick="jQueryAjaxComplecate();" value="jQueryAjaxComplecate" >
12 <script>
13     // TODO 简单的CORS请求, 请求的方法为 POST
14     function jQueryAjax() {
15         $.ajax({
16             url: ‘http://yhycn.com:8002/cors‘,
17             type: ‘POST‘,
18             data: {‘k1‘: ‘v1‘},
19             success: function (arg) {
20                 console.log(arg)
21             }
22         })
23     }
24
25     // TODO 复杂的cors, 请求的方式不是HEAD、GET、POST中的一种,满足复杂请求的要求, 可以自定义请求头,是否携带cookie
26     function jQueryAjaxComplecate() {
27         $.ajax({
28             url: ‘http://yhycn.com:8002/cors‘,
29             type: ‘PUT‘,
30             // 设置一个请求头,自定义请求头, 自定义了headers也是属于复杂的请求,因此需要在后台允许这样的headers
31             headers: {‘h1‘: ‘hh1‘},
32             // 指定在客户端跨域发送请求的时候,携带cookie
33             xhrFields:{withCredentials: true},
34             data: {‘k1‘: ‘v1‘},
35             success: function (arg) {
36                 console.log(arg);
37             }
38         })
39     }
40 </script>
41 </body>
42 </html>

请求代码

 1 # Python write by yhy
 2 # Python write by yhy
 3 import tornado.web
 4 import tornado.ioloop
 5
 6 class IndexHandler(tornado.web.RequestHandler):
 7     def get(self, *args, **kwargs):
 8         self.write(‘hello‘)
 9
10 class CorsHandler(tornado.web.RequestHandler):
11     def get(self, *args, **kwargs):
12         self.write(‘{"status": 1, "message": "get"}‘)
13
14     def post(self, *args, **kwargs):
15         # 服务端设置一个允许跨域的响应头,响应头的key=‘Access-Control-Allow-Origin‘, value=客户端的域名, * 表示所有的客户端都可以
16         self.set_header(‘Access-Control-Allow-Origin‘, ‘*‘)
17         self.write(‘{"status": 1, "message": "post"}‘)
18
19     # 这个是浏览器自动发送的域检请求
20     def options(self, *args, **kwargs):
21         # 指定允许客户端发送PUT请求
22         self.set_header(‘Access-Control-Allow-Origin‘, ‘http://yhy.com:8001‘)
23         self.set_header(‘Access-Control-Allow-Methods‘, ‘PUT, DELETE‘)
24         # 允许自定义的请求头通过
25         self.set_header(‘Access-Control-Allow-Headers‘, ‘h1, h2‘)
26         self.set_header(‘Access-Control-Allow-Credentials‘, ‘true‘)
27
28     def put(self, *args, **kwargs):
29         # 给客户端设置cookie值,当客户端请求的时候,会携带cookie值,
30         # TODO 应该注意的是,如果客户端跨域请求的时候携带了cookie值的话,那么需要将Access-Control-Allow-Origin的值设置为客户端的域名地址URL
31         print(self.cookies)
32         self.set_cookie(‘k1‘, ‘kkkk‘)
33         self.set_header(‘Access-Control-Allow-Origin‘, ‘http://yhy.com:8001‘)
34         self.set_header(‘Access-Control-Allow-Credentials‘, ‘true‘)
35         self.write(‘put‘)
36
37 settings = {
38     ‘template_path‘: ‘views‘,
39     ‘static_path‘: ‘statics‘,
40     ‘static_url_prefix‘: ‘/statics/‘,
41 }
42
43 application = tornado.web.Application([
44     (r‘/index‘, IndexHandler),
45     (r‘/cors‘, CorsHandler),
46 ], **settings)
47
48 if __name__ == ‘__main__‘:
49     application.listen(8002)
50     tornado.ioloop.IOLoop.instance().start()

服务端响应代码

时间: 2024-10-20 22:26:32

聊聊Ajax跨域的相关文章

jquery ajax跨域的完美解决方法(jsonp方式)

ajax跨域请求的问题,JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式,接下来为大家详细介绍下客户端JQuery.ajax的调用代码 今天在项目中需要做远程数据加载并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究,发 JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式.分别是JQuery的 jquery.ajax jsonp格式和jquer

Ajax跨域与解决方案

1.同步交互与异步交互 同步交互:用户在URL地址输入http://www.baidu.com,服务器接收请求并进行相应处理,此时用户无法操作,只能等待,只有当返回数据到客户端的时候,用户才能继续操作异步交互:用户操作某个页面,请求某个数据,客户可以继续操作(服务器返回数据),不涉及到整个页面的刷新 2.XmlHttp XmlHttp是一套可以在Javascript.VbScript.Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API.XmlHttp最大的用处是可

AJAX跨域

AJAX跨域AJAX不允许跨域访问. 跨域是指浏览器B显示的是服务器S1的数据,全是从S1取得的数据则是同域:但如果B显示的S1上的数据的某个比如img是从S2上取得的数据,则是跨域.端口不一样也是跨域.跨域不仅是跨服务器,还是跨IP,跨端口. AJAX通过三种方法,可以解决跨域问题. 1.设置请求头,每一个路径里都要设置,可以封装成方法方便调用.       res.setHeader("Access-Control-Allow-Origin","*");   

JQuery的Ajax跨域请求的

JQuery的Ajax跨域请求的(Ajax) 什么是jsonp格式呢?API原文:假设获取的数据文件存放在远程server上(域名不同.也就是跨域获取数据),则须要使用jsonp类型.使用这样的类型的话,会创建一个查询字符串參数 callback=? .这个參数会加在请求的URL后面. server端应当在JSON数据前加上回调函数名.以便完毕一个有效的JSONP请求.意思就是远程服务端须要对返回的数据做下处理,依据client提交的callback的參数,返回一个callback(json)的

Ajax跨域访问wcf服务中所遇到的问题总结。

工具说明:vs2012,sql server 2008R2 1.首先,通过vs2012建立一个wcf服务项目,建立好之后.再新开一个vs2012 建立web项目,通过jQuery的ajax方法访问服务. 问题:由于web项目和wcf服务,不在同一个端口之中,所以涉及到“跨域”的问题.跨域访问的时候,需要对服务的接口和方法做一定的限定.具体参考:http://www.cnblogs.com/yangbingqi/p/2096197.html 2.解决了跨域问题,我们需要把服务部署到IIS.vs20

AJAX是什么? AJAX的交互模型(流程)?同步和异步的区别? AJAX跨域的解决办法?

ajax是异步的 JavaScript 和 XML.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. 交互流程: 1--启动  获取XMlHttpRequest对象             2--open 打开url通道,并设置异步传输              3--send 发送数据到服务器             4--服务器接受数据并处理,处理完成后返回结果              5--客户端接收

解决Ajax跨域问题:Origin xx is not allowed by Access-Control-Allow-Origin.

解决Ajax跨域问题:Origin xx is not allowed by Access-Control-Allow-Origin. 今天一个Ajax跨域问题,纠结我半天,记录之. <html> <head> <title>title</title> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script>

Ajax 跨域请求 jsonp获取json数据

遇到Ajax的跨域请求出问题 找了中解决办法如下: 参考内容:http://justcoding.iteye.com/blog/1366102 由于受到浏览器的限制,该方法不允许跨域通信.如果尝试从不同的域请求数据,会出现安全错误.如果能控制数 据驻留的远程服务器并且每个请求都前往同一域,就可以避免这些安全错误.但是,如果仅停留在自己的服务器上,Web 应用程序还有什么用处呢?如果需要从多个第三方服务器收集数据时,又该怎么办? 理解同源策略 同源策略阻止从一个域上加载的脚本获取或操作另一个域上的

ajax跨域问题

提到ajax 大家比较头疼的是跨域问题,在项目中大多说都是以json格式来存储数据的,所以说我们今天就简单说一下利用jsonp形式来解决跨域问题,大家都知道只要带有src的标签都可以跨域请求,如img.script... 所以说解决ajax 跨域问题的关键是src标签,我们可以用script src 标签,然后再来个回调函数的方法解决跨域. 假如我们远程服务器有个alert.js,然后里面有alert("跨域成功"); 然后我们在有index.html, <!DOCTYPE ht