同源策略与跨域请求
Posted zh-xiaoyuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同源策略与跨域请求相关的知识,希望对你有一定的参考价值。
一、同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
jsonp(jsonpadding)
之前发ajax的时候都是在自己给自己的当前的项目下发
现在我们来实现跨域发。给别人的项目发数据,
创建两个项目,先来测试一下
项目一:Http://127.0.0.1:8006
views.py
from django.shortcuts import render,HttpResponse def index(request): return render(request,"index.html") def service(request): return HttpResponse("Project 1")
index.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h3>INDEX</h3> <button class="get_service">Project 1</button> <script src="/static/jquery-3.3.1.js"></script> <script> $(".get_service").click(function () { alert(123); $.ajax({ url: "http://127.0.0.1:8008/service/", success: function (data) { console.log(data) } }) }); </script> </body> </html>
项目二:Http://127.0.0.1:8006
views.py
from django.shortcuts import render,HttpResponse def index(request): return render(request,"index.html") def service(request): return HttpResponse("Project 2")
访问项目一的index界面
当点击Project 1 按钮时本应该跳转到项目二的service路径下给我们回一个响应,但此时报了一个错误:
这是因为同源策略给限制了,这是游览器给我们报的一个错。我们可以看到弹出了alert框,说明去项目二拿到了数据,只是浏览器不给我们显示。
注意:a标签,form,img标签,引用cdn的css等也属于跨域(跨不同的域拿过来文件来使用),不是所有的请求都给做跨域,(为什么要进行跨域呢?因为我想用人家的数据,所以得去别人的url中去拿,借助script标签)
只有发ajax的时候给拦截了,所以要解决的问题只是针对ajax请求能够实现跨域请求
二、解决同源策略的两种方法
1、基于jsonp实现跨域请求
将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。
jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。
项目一:
index.html
<script> $(".get_service").click(function () { $.ajax({ url: "http://127.0.0.1:8008/service/", type: "get", dataType: "jsonp", // 必须有,告诉service这次访问的是一个jsonp的结果 jsonp: ‘callbacks‘, //jsonpCallback:"alex", success: function (data) { //ajax拿到返回值(随机字符串)之后立即执行函数 console.log(data) } }) }); </script>
jsonp: ‘callbacks‘就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名,server端接受callback键对应值后就可以在其中填充数据打包返回了;
jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。利用jQuery可以很方便的实现JSONP来进行跨域访问。
注意 JSONP一定是GET请求
项目二:
views.py
from django.shortcuts import render,HttpResponse import json def service(request): # jsonp func=request.GET.get("callbacks") print("func",func) #func jQuery33105914359147116615_1589618121318 info={"name":"egon","age":34,"price":200} return HttpResponse("%s (‘%s‘)"%(func,json.dumps(info)))
再次访问项目一的index界面,点击Project 1按钮在控制台上就展现了我们向项目二所拿到的数据了。
2、基于cors实现跨域请求(比较常见的方式,简单)
只需在响应体中对 Access-Control-Allow-Origin进行设置
项目一:
index.html
<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>
在最开始我们就用上面的形式对项目二的service进行访问,但被浏览器拦截了,接下来我们只需在响应体中对 Access-Control-Allow-Origin进行设置就能够
实现跨域请求。
项目二:
view.py
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:8006" #只要是这个域来访问我就通过 #response["Access-Control-Allow-Origin"]="*" #所有域都能进行访问 return response
而且我们发现这种方式实现的跨域比基于jsonp实现跨域请求较为简单!
三、应用
// 跨域请求实例 $(".get_service").click(function () { $.ajax({ url:"http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403", dataType: ‘jsonp‘, jsonp: ‘callback‘, jsonpCallback: ‘list‘, success:function (data) { console.log(data.data); // [{},{},{},{},{},{}] week_list=data.data; $.each(week_list,function (i,j) { console.log(i,j); // 1 {week: "周一", list: Array(19)} s="<p>"+j.week+"列表</p>"; $(".show_list").append(s); $.each(j.list,function (k,v) { // {time: "0030", name: "通宵剧场六集连播", link: "http://www.jxntv.cn/live/jxtv2.shtml"} a="<p><a href=‘"+v.link+"‘>"+v.name+"</a></p>"; $(".show_list").append(a); }) }) } }) })
附:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h3>INDEX</h3> <button class="get_service">Project 1</button> <script src="/static/jquery-3.3.1.js"></script> <script> $(".get_service-0").click(function () { alert(123); $.ajax({ url: "http://127.0.0.1:8008/service/", success: function (data) { console.log(data) } }) }); function alex(arg) { console.log(arg); console.log(typeof arg); var data = JSON.parse(arg); console.log(data); console.log(typeof data); } function get_jsonp_data(url) { var ele_script = $("<script>"); <!--创建scr标签--> ele_script.attr("src", url); <!--为标签添加src属性--> ele_script.attr("id", "jsonp"); <!--为标签添加id属性--> $("body").append(ele_script); <!--把标签添加到body中--> $("#jsonp").remove() } <!--标签添加到body中后就已经执行了,执行之后删除标签--> $(".get_service").click(function () { $.ajax({ url: "http://127.0.0.1:8008/service/", success: function (data) { console.log(data) } }) }); $(".get_service-2").click(function () { get_jsonp_data("http://127.0.0.1:8008/service/?callbacks=alex") }); // 终极形式 $(".get_service-3").click(function () { $.ajax({ url: "http://127.0.0.1:8008/service/", type: "get", dataType: "jsonp", // 伪造ajax 基于script jsonp: ‘callbacks‘, //jsonpCallback:"alex", success: function (data) { //ajax拿到返回值(随机字符串)之后立即执行函数 console.log(data) } }) }); // 应用 $(".get_service-4").click(function () { $.ajax({ url: "http://www.jxntv.cn/data/jmd-jxtv2.html", type: "get", dataType: "jsonp", // 伪造ajax 基于script jsonp: ‘callbacks‘, jsonpCallback: "list", success: function (data) { //console.log(data.data); var html = ""; $.each(data.data, function (index, weekday) { console.log(weekday); // {week: "周一", list: Array(19)} html += ‘<p>‘ + weekday.week + ‘</p>‘; $.each(weekday.list, function (j, show) { html += ‘<p><a href=‘ + show.link + ‘>‘ + show.name + ‘</a></p>‘ }) }); $("body").append(html) } }) }) </script> </body> </html>
以上是关于同源策略与跨域请求的主要内容,如果未能解决你的问题,请参考以下文章