同源策略和解决

同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页
执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

 例子

项目一 index.html 端口 8000
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主页</h3>

<button class="get_service">点我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>

        $(".get_service").click(function () {
            $.ajax({
                url:"http://127.0.0.1:8008/service/",  // 注意 我请求的是另一个服务器
                success:function (data) {
                    console.log(data);
                }

            })
        });
</script>

项目二  view.py  端口 8008

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json
def service(request):
    info = {"name": "yk", "age": 20}

    return HttpResponse(json.dumps(info))

当我点击项目一 里的 button 按钮时,提示如下错误

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8008/service/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

Jsonp

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。其核心思想是利用JS标签里面的跨域特性进行跨域数据访问,

在JS标签里面存在的是一个跨域的URL,实际执行的时候通过这个URL获得一段字符串,这段返回的字符串必须是一个合法的JS调用,通过EVAL这个字符串来完成对获得的数据的处理。

jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略

项目一 index.html 端口 8000

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主页</h3>
<button class="get_service">点我</button> <script src="/static/jquery-3.3.1.js"></script> <script> function func(arg) { console.log(arg); console.log(typeof arg); data = JSON.parse(arg); console.log(data); console.log(typeof data); } </script> <script src="http://127.0.0.1:8008/service/"></script>

项目二  view.py  端口 8008

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json
def service(request):
    info = {"name": "yk", "age": 20}

    return HttpResponse("func('%s')" % json.dumps(info))

当再次刷新index.htnl

可以见到,成功访问到数据

项目一 index.html 端口 8000  点击按钮获取数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主页</h3>

<button class="get_service">点我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>
    function func(arg) {

        console.log(arg);
        console.log(typeof arg);

        data = JSON.parse(arg);
        console.log(data);
        console.log(typeof data);
    }

</script>

    $(".get_service").click(function () {#}

    $(".get_service").click(function () {

        var ele_script = $("<script>");

        ele_script.attr("src", "http://127.0.0.1:8008/service/");
        ele_script.attr("id", "jsonp");
        $("body").append(ele_script);

        $("#jsonp").remove();}
    )

</script>

jQuery对JSONP的实现

项目一 index.html 端口 8000

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>同源2</title>
</head>
<body>
<h3>主页</h3>

<button class="get_service">点我</button>

<script src="/static/jquery-3.3.1.js"></script>
<script>

    $(".get_service").click(function () {

        $.ajax({
            url: "http://127.0.0.1:8008/service/",
            type: "get",
            dataType: "jsonp",   //必须有,告诉server,这次访问要的是一个jsonp的结果。
            jsonp: "callbacks",  //jQuery帮助随机生成的:callbacks="jqueryxxxx"
       // jsonpCallback:"SayHi" ,  // 如果指定 ,则回调函数名 为SayHi
            success: function (data) {
                console.log(data)
            }
        })

    })

</script>

</body>
</html>

项目二  view.py  端口 8008

from django.shortcuts import render,HttpResponse

# Create your views here.

def index(request):

    return render(request,'index.html')

import json

def service(request):
    func = request.GET.get("callbacks")   # 获取 回调函数名

    info = {"name": "yk", "age": 20}

    return HttpResponse("%s('%s')" % (func,json.dumps(info)))

  jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',server端接受callback键对应值后就可以在其中填充数据打包返回了; 

  jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。  

注意 JSONP一定是GET请求

CORS

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,

代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers


def service(request):

    info={"name":"egon","age":34,"price":200}

    response=HttpResponse(json.dumps(info))
    response["Access-Control-Allow-Origin"]="http://127.0.0.1:8008"  # 设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
    #response["Access-Control-Allow-Origin"]="*"
    return  response
 
原文地址:https://www.cnblogs.com/ykgo/p/9489687.html