同源策略 - JSONP - CORS

 

 

1.  Jquery 对象能够经过 .index() 进行取出自当前元素在父级元素中存放的索引;javascript

2. 浏览器的同源策略 -- Ajax 在访问非本网站的时候,在数据返回的时候,会被浏览器拦截html

   - 后端使用 requests 获取数据后,发送给前端前端

   - jsonp 在前端页面中, 带有 src 属性的标签不受同源策略的影响(img, script, iframe等),咱们能够经过使用 script 标签来获取内容,但 script 中 src 获取内容后,得到到的字符串(相似于调用python中的 eval 或 exec)会被 JS 执行,因此咱们能够定义一个函数,而后让服务端返回的内容外面包裹一层这个函数名,前端在访问的时候把这个函数名发送过去,并提早定义好该函数java

手动实现:

服务端返回的数据python

 

def server(request):

    return HttpResponse("aaa('important data!!!')")

 

客户端定义及获取数据jquery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Client</title>
    <script src="/static/jquery-3.2.1.js"></script>
    <script>
        $(function(){

        });

        var url = 'http://127.0.0.1:8000/server.html/';  // 服务端路径
        var $script;                                     // 模拟使用建立的标签名
        function aaa(data){                              // 数据返回后用来接收的函数
            alert(data);
            document.head.removeChild($script);          // 接收完数据后,从页面删除刚才使用的标签
        }
        function getInfo(){
            $script = document.createElement("script");  // 建立一个 script 标签
            $script.setAttribute("src", url);            // 将须要请求数据的地址放入 script 的 src 中
            document.head.appendChild($script);          // 将标签放入到 head 中

        }

    </script>
</head>
<body>
    <h1>Client</h1>
    <input type="button" onclick="getInfo()" value="getInfo">
</body>
</html>

 

经过JSONP自动完成 - 上面是它的原理

 

 服务端返回的数据web

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse

def server(request):
    # 根据后端发送过来的名字来决定返回时,数据外面套的内容
    funcName = request.GET.get("callback")
    return HttpResponse("%s('important data!!!')"%funcName)

  客户端定义及获取数据ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Client</title>
    <script src="/static/jquery-3.2.1.js"></script>
    <script>
        function bbb(data){
            alert(data);
        }

        $(function(){
            var url = 'http://127.0.0.1:8000/server.html/';  // 服务端路径
            $.ajax({
                url: url,                   // 跨站请求数据的路径
                type: 'GET',                // 发送方式为 get, 因为使用的是 script, 因此只支持 get
                dataType: 'JSONP',          // 使用 JSONP 方式
                jsonp: 'callback',          // get 发送的时候,后面跟的数据名为 callback
                jsonpCallback: 'bbb'        // get 发送数据的callback的值为 bbb
            })
        });

    </script>
</head>
<body>
    <h1>Client</h1>
    <input type="button" value="getInfo">
</body>
</html>

 

cors - 跨域资源共享 cross origin resource sharing

随着技术的发展,如今的浏览器能够支持主动设置从而容许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器容许跨域请求。django

  cors 分为简单请求和非简单请求,简单请求只发送一次,直接发送数据,非简单请求则会发送两次数据,第一次发送 opption 请求(预检),为的是查看真正的数据是否能够被接收(数据头和请求方式是否符合要求), 若是符合要求,服务端能够把内容加入到头文件中来告诉浏览器;json

简单请求与非简单请求

条件:
    一、请求方式:HEAD、GET、POST
    二、请求头信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 对应的值是如下三个中的任意一个
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同时知足以上两个条件时,则是简单请求,不然为复杂请求

  

关于预检

- 请求方式:OPTIONS
- “预检”其实作检查,检查若是经过则容许传输数据,检查不经过则再也不发送真正想要发送的消息
- 如何“预检”
     => 若是复杂请求是PUT等请求,则服务端须要设置容许某请求,不然“预检”不经过
        Access-Control-Request-Method
     => 若是复杂请求设置了请求头,则服务端须要设置容许某请求头,不然“预检”不经过
        Access-Control-Request-Headers

  

简单请求:在使用cors的时候,客户端几乎不用修改,只须要按照普通的ajax的请求方式发送,在服务端返回数据的时候,只要在返回的时候,加上一个响应头就能够解决这个问题了

def example(request):
    response = HttpResponse("返回的数据内容")
    response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8888"  # 容许访问获取信息的域名
    return response

  服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*',容许访问获取信息的域名,若是后面是*的话,表明容许全部的请求,若是须要每个相应都设置该响应头的话(即这个网站的全部资源均可以被其它域名的所访问,那么咱们能够在中间件中设置这个响应头);

 

对于复杂请求,会先发一次预检(OPTIONS)请求,若是服务端容许,那么再发送一次正式请求(如PUT等,总之就是正真的请求),这个时候,咱们须要在后端进行判断,若是容许用户获取数据,那么当预检(OPTIONS)过来的时候,咱们须要返回容许访问的请求:Access-Control-Allow-Methds

if request.method == "OPTIONS":
    response = HttpResponse() // 返回的内容能够为空,主要须要返回请求头
    response['Access-Control-Allow-Origin'] = '*'
    response['Access-Control-Allow-Methods'] = 'PUT'   # 容许的复杂请求方式为 PUT 请求;若是多个,用逗号分隔, "PUT, DELETE"
    response['Access-Control-Allow-Headers'] = "k1"  # 复杂请求还有一种状况就是定制请求头,这种状况下,咱们在返回的相应中应该设置该响应头,表明容许发送请求头的key是什么,若是多个,逗号分隔 "k1, k2"
    return response

  若是咱们不想每次都通过“预检”这个环节的话,那么咱们能够在服务器的响应头中增长一组:Access-Control-Max-Age的响应头,能够写成

response['Access-Control-Allow-Headers'] = 10  # 默认单位为秒

  

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="x-ua-compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <title>Title</title>
 8     <script src="/static/jquery-3.2.1.js"></script>
 9     <script>
10         $(function(){
11             $("#btn01").click(function(){
12                 $.ajax({
13                     url: "http://127.0.0.1:8000/btn01/",
14                     success: function(data){
15                         console.log(data)
16                     }
17                 })
18             });
19 
20             $("#btn02").click(function(){
21                 $.ajax({
22                     url: "http://127.0.0.1:8000/btn02/",
23                     type: "PUT",
24                     success: function(data){
25                         console.log(data)
26                     }
27                 })
28             });
29 
30             $("#btn03").click(function(){
31                 $.ajax({
32                     url: "http://127.0.0.1:8000/btn03/",
33                     headers: {"k1": "asdfasdf"},
34                     success: function(data){
35                         console.log(data)
36                     }
37                 })
38             })
39         })
40     </script>
41 </head>
42 <body>
43 <p><input type="button" value="简单请求" id="btn01"></p>
44 <p><input type="button" value="复杂请求-PUT" id="btn02"></p>
45 <p><input type="button" value="复杂请求-Headers" id="btn03"></p>
46 </body>
47 </html>
简单和复杂请求的客户端代码
 1 from django.shortcuts import render
 2 from django.http import HttpResponse
 3 
 4 # Create your views here.
 5 def btn01(request):
 6     response = HttpResponse("btn01")
 7     response["Access-Control-Allow-Origin"] = "http://127.0.0.1:8888"
 8     return response
 9 
10 
11 def btn02(request):
12     if request.method == "OPTIONS":
13         response = HttpResponse()
14         response['Access-Control-Allow-Origin'] = '*'
15         response['Access-Control-Allow-Methods'] = 'PUT'
16         return response
17 
18     if request.method == "PUT":
19         response = HttpResponse("btn02")
20         response['Access-Control-Allow-Origin'] = '*'
21         return response
22 
23 
24 def btn03(request):
25     if request.method == "OPTIONS":
26         response = HttpResponse()
27         response['Access-Control-Allow-Origin'] = '*'
28         response['Access-Control-Allow-Headers'] = "k1"
29         return response
30 
31     if request.method == "GET":
32         response = HttpResponse("btn03")
33         response['Access-Control-Allow-Origin'] = '*'
34         return response
简单和复杂请求的服务端代码

 

 

携带cookie的传输

若是在使用Ajax请求的时候,须要传递cookie的时候,咱们则须要在发送ajax的时候,以及服务器给咱们相应的时候加上一组头信息

客户端须要加:XMLHttpRequest的withCredentials为true

$.ajax({
    url: "http://c2.com:8000/test/",
    type: 'PUT',
    dataType: 'text',
    headers: {'k1': 'v1'},
    xhrFields:{withCredentials: true},  // 加在了这里
    success: function(data, statusText, xmlHttpRequest){
        console.log(data);
    }
})

  

服务端须要加:Access-Control-Allow-Credentials为true

class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Credentials', "true")   # 加在了这里
        
        self.set_header('xxoo', "seven")
        self.set_header('bili', "daobidao")
        self.set_header('Access-Control-Expose-Headers', "xxoo,bili")

        self.set_cookie('kkkkk', 'vvvvv');

        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)

  

 

http://www.cnblogs.com/wupeiqi/articles/5703697.html

 

3. 模拟点击事件

$("#a").trigger("chick"); // 模拟执行 id=a 的事件

相关文章
相关标签/搜索