Cors實現跨域ajax,基本原理:客戶端不變,服務器端在返回響應數據時,添加響應頭讓瀏覽器允許其通過,
Cors實現跨域ajax很簡便,但不是所有瀏覽器都支持;sonp實現跨域,只能get請求;
一、瀏覽器發送簡單請求:服務器直接添加響應頭實現跨域
問:什么是簡單請求?
答:請求方式為head、get、post,且請求頭信息滿足條件
客戶端發送正常的ajax請求:

<!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>
服務器端添加響應頭實現跨域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()
二、瀏覽器發送復雜請求,需要預檢,通過才可發送正式請求
1、瀏覽器首先自動發送一個option請求預檢,如果預檢通過,返回可接受的訪問方式,
2、按可接受的訪問方式進行正式的請求,
注意:無論是預檢還是正式的請求,都是以簡單請求為基礎的,每一次都需要允許域名跨域的響應頭,

#!/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()

<!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); }, }); };
三、cros方式發送跨域Ajax,默認不傳遞cookie,需要客戶端攜帶cookie時,進行如下設置:
(1)客戶端設置:xhrFields:{withCredentials:'true'}, 表明攜帶cookie,
(2)服務器端設置:self.set_header('Access-Control-Allow-Credentials','true') ,表明允許客戶端攜帶cookie,
注意:允許攜帶cookie時,必須制定域名,不能用*,
另外:jsonp方式跨域,默認傳遞cookie,