首页 > 其他 > 详细

浏览器的同源策略,及如可跨域

时间:2020-06-08 17:51:34      阅读:37      评论:0      收藏:0      [点我收藏+]

1、同源策略

  所谓同源是指,域名,协议,端口相同。当一个浏览器的打开一个页面时中,页面请求非同源的URL时,请求能正常响应,但是浏览器会判断请求的URL和本页面的URL是否同源,

 

 

如果非同源的话,就会在本页面返回一个错误,并且得不到返回的数据。

2、解决跨域的方法

2.1、CORS通信实现跨域请求

  浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

  只要同时满足以下两大条件,就属于简单请求。 

(1) 请求方法是以下三种方法之一:(也就是说如果你的请求方法是什么put、delete等肯定是非简单请求)
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:(如果比这些请求头多,那么一定是非简单请求)
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain,也就是说,如果你发送的application/json格式的数据,那么肯定是非简单请求,vue的axios默认的请求体信息格式是json的,ajax默认是urlencoded的。

对于简单的请求只需要我么请求URL的响应函数views里面配置响应头Access-Control-Allow-Origin

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        function func(name) {
            alert(name)

        }
    </script>
    <script src="http://127.0.0.1:8001/base/"></script>
</head>
<body>

<form>
    <input type="button" id="id_button" value="button">

</form>
<script src="/static/jquery-2.1.4.min.js"> </script>
<script>
    $("#id_button").click(function () {
        $.ajax({
            url:http://127.0.0.1:8001/base/,
            type:GET,
            success:function () {
                alert(1111)

            }
        })

    })
</script>
</body>
</html>
index.html
技术分享图片
from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,index.html)

def base(request):
    response = HttpResponse(func("wuzhiib"))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
   # 在我们请求的URL的views里面设置,’*‘表示允许所有URL通过
    return response
views.py

浏览器对简单请求和复杂请求的处理是不一样的

* 简单请求和非简单请求的区别?

   简单请求:一次请求
   非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检”

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

如果在Ajax请求中加入ContentType就会使普通的请求变成复杂的请求。

 

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        function func(name) {
            alert(name)

        }
    </script>
    <script src="http://127.0.0.1:8001/base/"></script>
</head>
<body>

<form>
    <input type="button" id="id_button" value="button">

</form>
<script src="/static/jquery-2.1.4.min.js"> </script>
<script>
    $("#id_button").click(function () {
        $.ajax({
            url:http://127.0.0.1:8001/base/,
            type:GET,
            contentType:application/json,
            success:function () {
                alert(1111)

            }
        })

    })
</script>
</body>
</html>
index.html

 

对对于复杂的请求要在对应的头里面做设置,Contenttype只需要在响应头里面设置X-Content-Type-Options

技术分享图片
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse

# Create your views here.


def index(request):
    return render(request,index.html)

def base(request):
    response = HttpResponse(func("wuzhiib"))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
    response[Access-Control-Allow-Headers] = "content-type" #复杂请求ContentType的跨域方法
    return response
views.py

3、JsonP实现跨域

  非同源的URL不能阻止src属性的请求,也就是说通过src属性我们能跨域请求数据

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        function func(name) {
            alert(name)
        }
    </script>
    <!--利用script标签来实现跨域请求,返回的是func(‘‘wuzhibin),相当于实现上面func函数的调用-->
    <script src="http://127.0.0.1:8001/base/"></script>
</head>
<body>

<form>
    <input type="button" id="id_button" value="button">

</form>
<script src="/static/jquery-2.1.4.min.js"> </script>
<script>
    $("#id_button").click(function () {
        $.ajax({
            url:http://127.0.0.1:8001/base/,
            type:GET,
            contentType:application/json,
            success:function () {
                alert(1111)

            }
        })

    })
</script>
</body>
</html>
index.html
技术分享图片
from django.shortcuts import render,HttpResponse


def index(request):
    return render(request,index.html)

def base(request):
    response = HttpResponse(func("wuzhiib"))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
    response[Access-Control-Allow-Headers] = "content-type" #复杂请求ContentType的跨域方法
    #浏览器报错因为 MIME 类型(“text/html”)不匹配(X-Content-Type-Options: nosniff)
    response[X-Content-Type-Options] ="application/json" 
    return response
views.py

注意如果如果不配之响应头的X-Content-Type-Options属性,浏览器会报一个错误

技术分享图片

上面就是Jsonp实现的原理,这个只是哟个简单的例子,一般我们都需要能够动态的实现标签的创建

动态创建script标签

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="/static/jquery-2.1.4.min.js"> </script>
<button onclick="f()">sendAjax</button>
<!--动态创建标签Script-->
<script>
    function addScriptTag(src){
         var script = document.createElement(script);
         script.setAttribute("type","text/javascript");
         script.src = src;
         document.head.appendChild(script);
         // document.body.removeChild(script);
    }
    // 接受返回数据的回调函数
    function func(name){
        alert("hello"+name)
    }
    function f(){
         addScriptTag("http://127.0.0.1:8001/base/")
    }
</script>
</body>
</html>
index.Html

views.py与上面一直

技术分享图片
from django.shortcuts import render,HttpResponse


def index(request):
    return render(request,index.html)

def base(request):
    response = HttpResponse(func("wuzhiib"))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
    response[Access-Control-Allow-Headers] = "content-type" #复杂请求ContentType的跨域方法
    #浏览器报错因为 MIME 类型(“text/html”)不匹配(X-Content-Type-Options: nosniff)
    response[X-Content-Type-Options] ="application/json"
    return response
views.py

上面的例子中,我们在前端定义函数的时,另一个域明显是不知道我们我们前端定义的是func的,所以我们需要将函数名传给跨域的views函数动态生成返回函数名

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="/static/jquery-2.1.4.min.js"> </script>
<button onclick="f()">sendAjax</button>
<!--动态创建标签Script-->
<script>
    function addScriptTag(src){
         var script = document.createElement(script);
         script.setAttribute("type","text/javascript");
         script.src = src;
         document.head.appendChild(script);
         // document.body.removeChild(script);
    }
    // 接受返回数据的回调函数
    function func(name){
        var name=name
        alert("hello"+name)
    }
    function f(){
         addScriptTag("http://127.0.0.1:8001/base/?callbacks=func")
    }
</script>
</body>
</html>
index.html
技术分享图片
from django.shortcuts import render,HttpResponse


def index(request):
    return render(request,index.html)

def base(request):
    # 返回给跨域请求的数据
    data = wuzhibin
    #获取跨域请求的函数名
    callback = request.GET.get(callbacks)
    print(callback)

    response = HttpResponse("%s(‘%s‘)"%(callback,data))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
    response[Access-Control-Allow-Headers] = "content-type" #复杂请求ContentType的跨域方法
    #浏览器报错因为 MIME 类型(“text/html”)不匹配(X-Content-Type-Options: nosniff)
    response[X-Content-Type-Options] ="application/json"
    return response
view.py
Ajax中使用Jsonp

在实际的用处中,在Ajax中使用跨站请求数据的场景比较多一些。而不是单独生产动态生成一个Script标签去请求数据

技术分享图片
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse

def index(request):
    return render(request,index.html)

def base(request):
    import json
    # 返回给跨域请求的数据,一般都是字典的格式
    data = {
        key1:value1,
        key2:value2,
        k3:value3,
        k4:value4,
    }
    #等到跨域的方法名
    callbacks = request.GET.get("callbacks")

    response =HttpResponse("%s(‘%s‘)"%(callbacks,json.dumps(data)))
    response[Access-Control-Allow-Origin] =http://127.0.0.1:8000
    response[Access-Control-Allow-Headers] = "content-type" #复杂请求ContentType的跨域方法
    #浏览器报错因为 MIME 类型(“text/html”)不匹配(X-Content-Type-Options: nosniff)
    response[X-Content-Type-Options] ="application/json"
    return response
views.py
技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="/static/jquery-2.1.4.min.js"> </script>
<button onclick="f()">sendAjax</button>
<!--动态创建标签Script-->

<script>
function f(){
      $.ajax({  //大家会发现我的type请求方法没写,默认是get请求
            url:"http://127.0.0.1:8001/base/",
            dataType:"jsonp",
            jsonp: callbacks,
            jsonpCallback:"SayHi"
       });
   }
function SayHi(arg){
            // 将字符串转发为字典的格式
           var data = JSON.parse(arg);
            alert(data.key1);  //k1是后端返回的数据中的键值对的键
        }
</script>
</body>
</html>
index.html

 也能通过Ajax的success函数获取跨域的数据,这种方式比较简单些

技术分享图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="/static/jquery-2.1.4.min.js"> </script>
<button onclick="f()">sendAjax</button>
<!--动态创建标签Script-->

<script>
function f(){
      $.ajax({  //大家会发现我的type请求方法没写,默认是get请求
            url:"http://127.0.0.1:8001/base/",
            dataType:"jsonp",
            jsonp: callbacks,
            jsonpCallback:"SayHi",
            success:function (rag) {
                var data = JSON.parse(rag)
                alert(data.key1)
            }
       });
   }
</script>
</body>
</html>
index.html

views.py函数和上面保持一致

浏览器的同源策略,及如可跨域

原文:https://www.cnblogs.com/wuzhibinsuib/p/13066532.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!