zoukankan      html  css  js  c++  java
  • 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);
                }
            })
        }
    View Code

    服务端完整:

    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')
    View Code

    更多信息来源可以看此处

    简单请求 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-ID
            Content-Type 对应的值是以下三个中的任意一个
                                    application/x-www-form-urlencoded
                                    multipart/form-data
                                    text/plain
     
    注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
  • 相关阅读:
    测试面试题
    订单怎么测试?(主要测试订单的状态变化)
    还款功能怎么测试?
    登录功能怎么测试?
    apache配置详解与实践
    apache的安装
    linux系统优化(关闭SElinux、防火墙)
    linux网络配置
    linux的日志管理
    python的xlwt模块
  • 原文地址:https://www.cnblogs.com/ssyfj/p/8536011.html
Copyright © 2011-2022 走看看