Cors实现跨域ajax,基本原理:客户端不变,服务器端在返回响应数据时,添加响应头让浏览器允许其通过,

 Cors实现跨域ajax很简便,但不是所有浏览器都支持;sonp实现跨域,只能get请求;


一、浏览器发送简单请求:服务器直接添加响应头实现跨域

  问:什么是简单请求?

  答:请求方式为head、get、post,且请求头信息满足条件

    

客户端发送正常的ajax请求:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <input type="button" value="Ajax" onclick="DoAjax();" />
    <script src="sss/jquery-1.12.4.min.js"></script>
    <script>
        function DoAjax(){
            $.ajax({
                url:'http://ajax2.com:8888/index',
                type:'POST',
                data:{'k1':'v1'},
                success:function(arg){ console.log(arg); },
            });
        };
    </script>
</body>
</html>
 Code

服务器端添加响应头实现跨域ajax:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop
import tornado.web

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("ajax2_get")

    def post(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin','http://ajax1.com:8001')  # 添加响应头,允许指定域名的跨域请求
        self.write("ajax2_post")

# 路径解析
settings = {
    "template_path":"views",
    "static_path":"statics",
    "static_url_prefix":"/sss/",
}

# 二级路由,先匹配域名,
application = tornado.web.Application([
    (r"/index",IndexHandler),
],**settings)


# 开启服务器,监听
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
View Code

二、浏览器发送复杂请求,需要预检,通过才可发送正式请求

1、浏览器首先自动发送一个option请求预检,如果预检通过,返回可接受的访问方式,

2、按可接受的访问方式进行正式的请求,

注意:无论是预检还是正式的请求,都是以简单请求为基础的,每一次都需要允许域名跨域的响应头,

s_py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop
import tornado.web

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("ajax2_get")

    # 简单请求
    def post(self, *args, **kwargs):
        # 添加响应头,允许指定域名的跨域请求
        # self.set_header('Access-Control-Allow-Origin','http://ajax1.com:8001,')  # 可同时指定多个域名,用逗号隔开,
        self.set_header('Access-Control-Allow-Origin','*')                       # *表示所有域名都可以进行跨域申请
        self.write("ajax2_post")

    # 复杂请求的预检
    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin','*')                    # 指明允许请求的域名,可以是具体域名
        self.set_header('Access-Control-Allow-Methods','PUT,DELETE')         # 指明允许请求的方法,可多个,但不能是*,
        self.set_header('Access-Control-Allow-Headers','h1,h2,')             # 指明允许通过的header,有时客户端会设置,
        #  self.set_header('Access-Control-Max-Age',10)                          # 设置有效时间,秒
    # 复杂请求
    def put(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin','*')
        self.write('put')

# 路径解析
settings = {
    "template_path":"views",
    "static_path":"statics",
    "static_url_prefix":"/sss/",
}

# 二级路由,先匹配域名,
application = tornado.web.Application([
    (r"/index",IndexHandler),
],**settings)


# 开启服务器,监听
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
 Code
c_html
<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <input type="button" value="SimpleAjaxCors" onclick="DoSimpleAjax();" />
    <input type="button" value="ComplexAjaxCors" onclick="DoComplexAjax();" />
    <script src="sss/jquery-1.12.4.min.js"></script>
    <script>
        function DoSimpleAjax(){
            $.ajax({
                url:'http://ajax2.com:8888/index',
                type:'POST',
                data:{'k1':'v1'},
                success:function(arg){ console.log(arg); },
            });
        };

        function DoComplexAjax(){
            $.ajax({
                url:'http://ajax2.com:8888/index',
                type:'PUT',
                data:{'k1':'v1'},
                headers:{'h1':'xxoo'},   <!--需要服务器端设置header-->
                success:function(arg){ console.log(arg); },
            });
        };
 Code 

 三、cros方式发送跨域Ajax,默认不传递cookie,需要客户端携带cookie时,进行如下设置:

(1)客户端设置:xhrFields:{withCredentials:'true'},  表明携带cookie,

(2)服务器端设置:self.set_header('Access-Control-Allow-Credentials','true')  ,表明允许客户端携带cookie,

 

注意:允许携带cookie时,必须制定域名,不能用*,

 另外:jsonp方式跨域,默认传递cookie,