ajax跨域原理 cors跨域资源共享
Posted 山上有风景
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ajax跨域原理 cors跨域资源共享相关的知识,希望对你有一定的参考价值。
不需要设置前端太多,只需要在服务端是在请求头,使服务端的回复数据可以正常通过浏览器的限制,进入网站
首先说下简单请求和非简单请求:
简单请求:必须满足下列条件
1.请求方式:head,get,post
2.请求头
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:其对应值限制为3个application/x-www-form-urlencoded,multipart/form-data,text/plain
必须同时满足上面的两个条件叫做简单请求
简单请求:跨站请求时只需要一次请求
非简单请求:两次请求,在发送请求之前会先发送一次请求(预检),通过预检的才能再次发送一次请求进行数据传输
一:简单请求
前端:正常设置信息
function CorsAjax(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"post", success:function(data){ console.log(data); } }) }
后台服务端(跨域方)需要设置请求头:
#简单请求 def post(self, *args, **kwargs): self.set_header(\'Access-Control-Allow-Origin\',"http://www.py_test1.com:8080,http://www.py_test1.com:8080")#设置一个或多个都可以,或者加上*代表所有的都允许 self.write(\'{"status":1,"message":"post"}\')
二:复杂请求:需要先发送一次预检
而预检的请求方式为options,所以我们需要在服务端设置一个options请求来处理预检信息
1.当前端的请求方式不满足条件时:
//复杂请求,会发送两个请求,一个options一个put function CorsAjax2(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"put", success:function(data){ console.log(data); } }) }
需要在服务端设置预检
#复杂请求 def options(self, *args, **kwargs):#第一次用于预检 #先允许网站接入 self.set_header(\'Access-Control-Allow-Origin\', "http://www.py_test1.com:8080") #若是请求方法不满足get,post,head self.set_header(\'Access-Control-Allow-Methods\',"PUT,DELETE")#还可以添加其他,比如DELETE,不能是*
def put(self, *args, **kwargs):#第二次为请求,用于数据传输
self.set_header(\'Access-Control-Origin\',\'http://www.py_test1.com:8080\') #也要设置源地址 self.write(\'put ok\')
2.当客户端请求头也不满足时:
//复杂请求,会发送两个请求,一个options一个put function CorsAjax2(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"put", headers:{\'k1\':\'ddasf\',"k2":\'fa\'}, success:function(data){ console.log(data); } }) }
服务端需要设置关于请求头的信息
#复杂请求 def options(self, *args, **kwargs):#第一次用于预检 #先允许网站接入 #self.set_header(\'Access-Control-Allow-Origin\',"*") # 或者加上*代表所有的都允许 #如果客户端允许传递cookie,那么这里请求头就不能是*,必须是指定的url self.set_header(\'Access-Control-Allow-Origin\', "http://www.py_test1.com:8080") #若是请求方法不满足get,post,head self.set_header(\'Access-Control-Allow-Methods\',"PUT,DELETE")#还可以添加其他,比如DELETE,不能是* #若是请求头也不满足简单请求,也需要设置 self.set_header(\'Access-Control-Allow-Headers\', "k1,k2")#客户端自定义请求头
对于客户端预检可以设置缓存时间,在相应时间内,不会再进行预检
#可以设置缓存时间,原来需要一次预检一次请求,现在只需要一次请求 self.set_header(\'Access-Control-Max-Age\',10)#10秒内不再产生预检
对于请求头,若是服务端想要自定义请求都传入客户端:需要进行以下操作
def put(self, *args, **kwargs):#第二次为请求 #服务端自定义响应头 #self.set_header(\'xxoo\',\'seven\') #self.set_header(\'bili\',\'daobidao\')#这样是客户端无法接收 #还需要设置一条 #self.set_header(\'Access-Control-Expose-Headers\',"xxoo,bili")
3.当客户端允许携带cookie时
需要在客户端设置XMLHttpRequest的withCredentials为true
//复杂请求,会发送两个请求,一个options一个put function CorsAjax2(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"put", headers:{\'k1\':\'ddasf\',"k2":\'fa\'}, xhrFields:{withCredentials:true},//默认是不允许携带cookie和ssl证书等,需要设置,服务端也要相应设置 success:function(data){ console.log(data); } }) }
注意在服务端响应时不允许设置Access-Control-Allow-Origin为通配符*
#若是客户端传递cookie进入,需要设置允许证书等 self.set_header(\'Access-Control-Allow-Credentials\',"true")
完整代码
#复杂请求 def options(self, *args, **kwargs):#第一次用于预检 #先允许网站接入 #self.set_header(\'Access-Control-Allow-Origin\',"*") # 或者加上*代表所有的都允许 #如果客户端允许传递cookie,那么这里请求头就不能是*,必须是指定的url self.set_header(\'Access-Control-Allow-Origin\', "http://www.py_test1.com:8080") #若是请求方法不满足get,post self.set_header(\'Access-Control-Allow-Methods\',"PUT,DELETE")#还可以添加其他,比如DELETE,不能是* #若是请求头也不满足简单请求,也需要设置 self.set_header(\'Access-Control-Allow-Headers\', "k1,k2")#客户端自定义请求头 #若是客户端传递cookie进入,需要设置允许证书等 self.set_header(\'Access-Control-Allow-Credentials\',"true") #可以设置缓存时间,原来需要一次预检一次请求,现在只需要一次请求 self.set_header(\'Access-Control-Max-Age\',10)#10秒内不再产生预检
在第二次请求中:可以设置cookie,并获取
def put(self, *args, **kwargs):#第二次为请求 #由于设置了cookie,所有这里不允许* #self.set_header(\'Access-Control-Allow-Origin\', "*") self.set_header(\'Access-Control-Allow-Origin\',"http://www.py_test1.com:8080") self.set_header(\'Access-Control-Allow-Credentials\',"true") #为跨域站点设置cookie print(self.cookies) self.set_cookie(\'kk\',\'21\') self.write(\'put ok\')
注意第二次请求也是需要设置Access-Control-Allow-Origin的
而且由于cookie的添加需要设置Access-Control-Allow-Credentials
前端完整:
<script> function CorsAjax(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"post", success:function(data){ console.log(data); } }) } //复杂请求,会发送两个请求,一个options一个put function CorsAjax2(){ $.ajax({ url:\'http://www.py_test2.com:8081/cors\', dataType:\'text\', data:{}, type:"put", headers:{\'k1\':\'ddasf\',"k2":\'fa\'}, xhrFields:{withCredentials:true},//默认是不允许携带cookie和ssl证书等,需要设置,服务端也要相应设置 success:function(data){ console.log(data); } }) }
服务端完整:
class CorsHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write(\'{"status":1,"message":"get"}\') #简单请求 def post(self, *args, **kwargs): self.set_header(\'Access-Control-Allow-Origin\',"http://www.py_test1.com:8080,http://www.py_test1.com:8080")#或者加上*代表所有的都允许 self.write(\'{"status":1,"message":"post"}\') #复杂请求 def options(self, *args, **kwargs):#第一次用于预检 #先允许网站接入 #self.set_header(\'Access-Control-Allow-Origin\',"*") # 或者加上*代表所有的都允许 #如果客户端允许传递cookie,那么这里请求头就不能是*,必须是指定的url self.set_header(\'Access-Control-Allow-Origin\', "http://www.py_test1.com:8080") #若是请求方法不满足get,post self.set_header(\'Access-Control-Allow-Methods\',"PUT,DELETE")#还可以添加其他,比如DELETE,不能是* #若是请求头也不满足简单请求,也需要设置 self.set_header(\'Access-Control-Allow-Headers\', "k1,k2")#客户端自定义请求头 #若是客户端传递cookie进入,需要设置允许证书等 self.set_header(\'Access-Control-Allow-Credentials\',"true") #可以设置缓存时间,原来需要一次预检一次请求,现在只需要一次请求 self.set_header(\'Access-Control-Max-Age\',10)#10秒内不再产生预检 def put(self, *args, **kwargs):#第二次为请求 #服务端自定义响应头 #self.set_header(\'xxoo\',\'seven\') #self.set_header(\'bili\',\'daobidao\')#这样是客户端无法接收 #还需要设置一条 #self.set_header(\'Access-Control-Expose-Headers\',"xxoo,bili") #由于设置了cookie,所有这里不允许* #self.set_header(\'Access-Control-Allow-Origin\', "*") self.set_header(\'Access-Control-Allow-Origin\',"http://www.py_test1.com:8080") self.set_header(\'Access-Control-Allow-Credentials\',"true") #为跨域站点设置cookie print(self.cookies) self.set_cookie(\'kk\',\'21\') self.write(\'put ok\')
更多信息来源可以看此处
简单请求 OR 非简单请求
1
2
3
4
5
6
7
8
9
10
11
12
13
|
条件: 1 、请求方式:HEAD、GET、POST 2 、请求头信息: Accept Accept - Language Content - Language Last - Event - ajax跨域原理以及解决方案
|