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,
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步