关于跨域介绍和djiago解决跨域问题
什么是跨域?
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
什么是同源策略?
同源策略又分为以下两种
- DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。 - 只要协议、域名、端口有任何一个不同,都被当作是不同的域,之间的请求就是跨域操作
所谓同源是指,域名,协议,端口 均相同
如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,
则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
客户端JavaScript程序。虽然是一种解释性的脚本语言,JavaScript其实是无比强大的,原则上来讲它可以做任何事。
但是在能够在JavaScript脚本并不都是值得信赖的,所以浏览器必须对JavaScript的执行作相应的限制。
比如我们ajax可以随便发送一个请求就能取到数据,修改数据,那我们每个人都是黑客了。很多敏感信息就泄露。
但是对src等请求是没有限制的。
为什么我们需要跨域限制?
主要是出于安全的考虑
AJAX同源策略主要用来防止CSRF攻击。如果没有AJAX同源策略,相当危险,
我们发起的每一次HTTP请求都会带上请求地址对应的cookie,那么可以做如下攻击:
- 用户登录了自己的银行页面 http://mybank.com,http://mybank.com向用户的cookie中添加用户标识。
- 用户浏览了恶意页面 http://evil.com。执行了页面中的恶意AJAX请求代码。
- http://evil.com向http://mybank.com发起AJAX HTTP请求,请求会默认把http://mybank.com对应cookie也同时发送过去。
- 银行页面从发送的cookie中提取用户标识,验证用户无误,response中返回请求数据。此时数据就泄露了。
- 而且由于Ajax在后台执行,用户无法感知这一过程。
DOM同源策略也一样,如果iframe之间可以跨域访问,可以这样攻击:
- 做一个假网站,里面用iframe嵌套一个银行网站 http://mybank.com。
- 把iframe宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没有任何差别。
- 这时如果用户输入账号密码,我们的主网站可以跨域访问到http://mybank.com的dom节点,就可以拿到用户的输入了,那么就完成了一次攻击。
解决跨区:
合理的跨域访问---CORS
CORS:”跨域资源共享”(Cross-origin resource sharing),这是一个W3C标准
CORS需要浏览器和服务器同时支持。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信
CORS可以分成两种:
1、简单请求
- 请求方式:GET、POST、HEAD(注:什么是HEAD请求?HEAD请求和GET本质是一样的,但是HEAD请求不含数据,只有HTTP头部信息)
- HTTP头部信息不超过一下几种字段:
- 无自定义头部字段、
- Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
2、复杂请求
- 请求方式:PUT、DELETE
- 自定义头部字段
- 发送json格式数据
- 正式通信之前,浏览器会先发送OPTION请求,进行预检,这一次的请求称为“预检请求”
- option是什么?
- (
OPTION会
请求询问服务器,你支持哪种请求方法啊?
服务端响应支持GET,POST和OPTION等。。
) - 服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
简单请求
一个简单的请求大致如下: HTTP方法是下列之一 HEAD
GET
POST HTTP头信息不超出以下几种字段 Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type,但仅能是下列之一
application/x-www-form-urlencoded
multipart/form-data
text/plain
任何一个不满足上述要求的请求,即被认为是复杂请求。一个复杂请求不仅有包含通信内容的请求,同时也包含预请求(preflight request)。
简单请求的部分响应头及解释如下:
Access-Control-Allow-Origin(必含)- 不可省略,否则请求按失败处理。该项控制数据的可见范围,如果希望数据对任何人都可见,可以填写"*"。
Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)
。如果不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,
即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则导致请求失败。
Access-Control-Expose-Headers(可选) – 该项确定XmlHttpRequest2对象当中getResponseHeader()方法所能获得的额外信息。
通常情况下,getResponseHeader()方法只能获得如下的信息:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
当你需要访问额外的信息时,就需要在这一项当中填写并以逗号进行分隔
复杂请求
Access-Control-Request-Method
该项内容是实际请求的种类,可以是GET、POST之类的简单请求,也可以是PUT、DELETE等等。
Access-Control-Request-Headers
该项是一个以逗号分隔的列表,当中是复杂请求所使用的头部。
多了一个OPTIONS的预检请求,例如
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...`
服务器需要对预检请求进行回应
服务器收到"预检"请求以后,检查了Origin
、Access-Control-Request-Method
和Access-Control-Request-Headers
字段以后,
确认允许跨源请求,就可以做出回应。
> HTTP/1.1 OK
> Date: Mon, Dec :: GMT
> Server: Apache/2.0. (Unix)
> Access-Control-Allow-Origin: http://api.bob.com
> Access-Control-Allow-Methods: GET, POST, PUT
> Access-Control-Allow-Headers: X-Custom-Header
> Content-Type: text/html; charset=utf-
> Content-Encoding: gzip
> Content-Length:
> Keep-Alive: timeout=, max=
> Connection: Keep-Alive
> Content-Type: text/plain
Access-Control-Allow-Origin(必含)
– 和简单请求一样的,必须包含一个域。
Access-Control-Allow-Methods(必含)
– 这是对预请求当中Access-Control-Request-Method的回复,
这一回复将是一个以逗号分隔的列表。尽管客户端或许只请求某一方法,但服务端仍然可以返回所有允许的方法,以便客户端将其缓存。
Access-Control-Allow-Headers(当预请求中包含Access-Control-Request-Headers时必须包含)
这是对预请求当中Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。
这里在实际使用中有遇到,所有支持的头部一时可能不能完全写出来,而又不想在这一层做过多的判断,没关系,
事实上通过request的header可以直接取到Access-Control-Request-Headers,直接把对应的value设置到Access-Control-Allow-Headers即可。
Access-Control-Allow-Credentials(可选)
– 和简单请求当中作用相同。
Access-Control-Max-Age(可选)
– 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存
XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
(1)Access-Control-Allow-Methods 授权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。
注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
(2)Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
(3)Access-Control-Allow-Credentials
该字段与简单请求时的含义相同。
(4)Access-Control-Max-Age
该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),
即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。
(5)Access-Control-Allow-Origin:指定授权访问的域
response.addHeader("Access-Control-Allow-Origin", "http://192.168.56.130");
浏览器的正常请求和回应
下面是"预检"请求之后,浏览器的正常CORS请求。
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
上面头信息的Origin
字段是浏览器自动添加的。
下面是服务器正常的回应。
Access-Control-Allow-Origin: http://api.bob.com
> Content-Type: text/html; charset=utf-
own:
基于django的cors跨域例子:
在服务端的设置:
def service(request):
# 你需要跨域传的数据
info = {"name": "egon", "age": 34, "prive": 200} response = HttpResponse(json.dumps(info))
# 解决跨域问题 * 表示允许所有的跨域请求
response["Access-Control-Allow-Origin"] = "*"
# 在djiango 2.26版本中 经过我实验下面这个方法没用
# response['Access-Control-Allow-Origin'] = "http://127.0.0.1:8006/"
return response
Django 解决跨域问题
方案一:
在app下创建一个middlewares的py文件:
from django.utils.deprecation import MiddlewareMixin class MyTest(MiddlewareMixin):
def process_response(self, request, response):
response['Access-Control-Allow-Origin'] = '*'
return response
其他字段:
方案二:
django 使用django-cors-headers 解决跨域问题(待测试)
1. 安装
pip install django-cors-headers
2.添加到setting的app中
INSTALLED_APPS = (
...
'corsheaders',
...
)
3.添加中间件
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
4、setting下面添加下面的配置
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
'*'
)
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
) CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
解决跨域问题jsonnp script简单版原理
http://127.0.0.1:8006/ 端口(我是向8007跨域请求端)
前端页面:
<button class="get_service">洗剪吹</button> </body> <script>
// 跨域端口返回get_jsonp_data函数调用,将值以arg形式传进来。
function get_jsonp_function(arg) {
alert(arg);
console.log(typeof arg);
var data = JSON.parse(arg);
console.log(data);
console.log(typeof data);
}
</script> <script>
//点击向跨域端口发送一次service请求 function get_jsonp_data(url) {
//创建一个script标签
var ele_svript = $("<script>");
//添加一个src属性
ele_svript.attr("src", url);
ele_svript.attr("id", "jsonp");
// 添加到body文档树后面
$("body").append(ele_svript);
//将多余的文档删除
$("#jsonp").remove()
}
</script> <script>
$(".get_service").on("click", function () {
//以另一端传过来的接口?callback= 自定义我们的函数名
get_jsonp_data("http://127.0.0.1:8007/service/?callback=get_jsonp_function"); })
</script>
</html>
http://127.0.0.1:8007/ 端口(我是服务端)
view视图端
from django.shortcuts import render, HttpResponse
import json # Create your views here. def index(request):
return render(request, "index.html") def service(request): # 你需要跨域传的数据
info = {"name": "egon", "age": 34, "prive": 200} # 前端自己创建函数名,我只要给那边一个callback接口就行
func = request.GET.get("callback") return HttpResponse("%s('%s')" % (func, json.dumps(info),))
jsonp跨域请求:
什么是jsonp?
JSON & JSONP:JSON 是一种基于文本的数据交换方式,或者叫做数据描述格式。
JSONP是资料格式JSON的一种“使用模式”,可以让网页从别的网域要资料,由于同源策略,
一般来说位于server1.example.com的网页无法与不是 server1.example.com的服务器沟通,而HTML的script元素是一个例外。
利用script元素的这个开放策略,网页可以得到从其他来源动态产生的JSON资料,而这种使用模式就是所谓的JSONP。
缺点:
1.JSONP只能实现GET请求。
2.JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
3.也就是说在浏览器支持cors的情况下 尽量使用cors方式。
JSONP高级版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--配置手机端适应-->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!--配置css文件 核心CSS样式压缩文件-->
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/font-awesome-4.7.0/css/font-awesome.css">
<!--配置jQuery-->
<script src="/static/bootstrap/jQuery.js"></script>
<!--配置 核心Boot script JS压缩文件-->
<script src="/static/bootstrap/js/bootstrap.min.js"></script> </head>
<body>
<h3>Idext</h3> <button class="get_service">洗剪吹</button> </body> <script>
// 跨域端口返回get_jsonp_data函数调用,将值以arg形式传进来。
function get_jsonp_function(arg) {
alert(arg);
console.log(typeof arg);
var data = JSON.parse(arg);
console.log(data);
console.log(typeof data);
}
</script> <script>
//终极模式
$(".get_service").on("click", function () {
$.ajax({
url: "http://127.0.0.1:8007/service/",
type: "get",
dataType: "jsonp", //伪造ajax 基于script
jsonpCallback:"get_jsonp_function", //服务端需要传并且客户端需要执行的函数,
success: function (data) { // 数据也可以从success传进来并进行数据操作 }
})
}) </script> </html>
服务端:
from django.shortcuts import render, HttpResponse
import json # Create your views here. def index(request):
return render(request, "index.html") def service(request):
# 你需要跨域传的数据
info = {"name": "egon", "age": 34, "prive": 200} # 可以让跨区哪一步自己创建函数名,我只要给那边一个callback接口就行
func = request.GET.get("callback") return HttpResponse("%s('%s')" % (func, json.dumps(info),))
一个跨域的实战列子:
<script>
//示例
$(".get_service").on("click", function () {
$.ajax({
url: "http://www.jxntv.cn/data/jmd-jxtv2.html",
type: "get",
dataType: "jsonp", //伪造ajax 基于script
jsonp: "callbacks", //需要发送伪造的服务端的函数名称
jsonpCallback:"list" ,//服务端需要并执行的函数,服务端以经定好了list所以必须要以list接受
success: function (data) {
console.log(data);
//数据处理 var html="";
// each 是jquery中的循环
$.each(data.data,function (index,weekday) {
console.log(weekday); // {week: "周日", list: Array(19)}
// 我自定义了一个p标签,并且取出了字段中week的值。
html+='<p>'+weekday.week+'<p>'; // 加等于的意思就是就是叠加。 $.each(weekday.list, function (j,show) {
html+='<a href='+show.link+'>'+show.name+'</a>' }) });
//找到body添加到后面
$("body").append(html) }
})
}) </script>
关于跨域介绍和djiago解决跨域问题的更多相关文章
- 搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理
什么是跨域 跨域:一个域下的文档或脚本试图去请求另一个域下的资源 广义的跨域包含一下内容: 1.资源跳转(链接跳转,重定向跳转,表单提交) 2.资源请求(内部的引用,脚本script,图片img,fr ...
- Web API 解决跨域问题
一.跨域问题的由来 同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容. 正是由于这个原因,我们不同项目之间的调用就会被浏览器阻 ...
- 一篇文章让你搞懂如何通过Nginx来解决跨域问题
Nginx跨域实现 首先大家要搞清楚什么是跨域,为什么会有跨域情况的出现.哪些情况属于跨域? 跨域:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容 注:同源策略,单说来就是 ...
- 无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离
近年来,前后端分离已经成为中大型软件项目开发的最佳实践. 在技术层面,前后端分离指在同一个Web系统中,前端服务器和后端服务器采用不同的技术栈,利用标准的WebAPI完成协同工作.这种前后端分离的&q ...
- Axiso解决跨域访问(...XMLHttpRequest cannot load http://xxx.xxx No 'Access-Control-Allow-Origin'...)
直接访问如下:this.$axios.get("http://localhost:8089/yc/demo").then(res=>{ console.log(res) ...
- nginx反向代理解决跨域问题
跨域:浏览器从一个域名的网页去请求另一个域名的资源时,域名.端口.协议任一不同,都是跨域 . 下表格为前后端分离的域名,技术信息: 域名 服务器 使用技术 前端 http://b.yynf.com ...
- Java解决跨域问题
同源 URL由协议, 域名, 端口组成. 如果两个URL的协议, 域名, 端口相同, 那么这两个URL为同源. 同源策略 script, iframe, link 可以跨域加载一些静态资源, 比如脚本 ...
- CORS-跨域资源共享 解决跨域问题
1.什么是跨域? a.test.com 和 b.test.com 是两个不同的域,而处于安全机制考虑,JS只能访问与所在页面同一个域(相同协议.域名.端口)的内容,但是我们在项目开发时,经常遇到一个页 ...
- Axiso解决跨域访问
问题: 在项目中需要需要讲本地项目去请求一个URL接口获取数据 例如: 本地请求地址:http://127.0.0.1:19323/site/info.json 请求Url地址:http://www. ...
随机推荐
- 函数的练习2——python编程从入门到实践
8-9 魔术师:创建一个包含魔术师名字的列表,并将其传递一个名为show_magicians()的函数,这个函数打印列表中每个魔术师的名字. def show_magicians(magicians) ...
- PAT(B) 1090 危险品装箱(Java)
题目链接:1090 危险品装箱 (25 point(s)) 题目描述 集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里.比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸. 本题 ...
- 在bat批处理中简单的延时方法
使用for命令: 延时1s左右的方法: @echo off echo %time% ,,) do echo %%i>nul echo %time% pause %time%是用来显示延时时间,实 ...
- xorm实例-创建xorm,映射
创建xorm引擎 //在xorm里面,可以同时存在多个Orm引擎,一个Orm引擎称为Engine, //一个Engine一般只对应一个数据库. //Engine通过调用`xorm.NewEngine` ...
- postman调用webapi错误记录
1.webapi ,接口中header中,value 不能太长,太长会报错 结局:value中不要存太长的数据 2.如果key 中有中文,会获取不到数据 , 解决:需要把中文转码,然后后端解码 3.如 ...
- DevExtreme学习笔记(一)treeView(搜索固定、节点展开和收缩)注意事项
var treeConfig1 = dxConfig.treeView(obj_Question.treeDataSource1); treeConfig1.selectionMode = 'sing ...
- Java NIO和IO的区别
下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异. 复制代码 代码如下: IO NIO面向流 面向缓冲阻塞IO 非阻塞IO无 选择器 面向流与面向缓冲 Java NIO ...
- atan、atanf、atanl、atan2、atan2f、atan2l
很久不发博客了,今天在园中计算各种角,于是复习下fan正切函数 计算x的反正切值 (atan.atanf和 atanl) 或y/x 的反正切值 (atan2.atan2f和 atan2l). ...
- JAVA基础之ServletContext对象
个人理解: ServletContext类似字节码文件对象,在web创建的时候就自动生成了,并且是唯一的,跟随着项目和服务器共存亡了.通过这个对象,我们可以向里面存数据(键值对),也可以通过别的Se ...
- 【雅思】【绿宝书错词本】List37~48
List 37 ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ List 38 ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ ❤ List 39 ✔ ✔ ✔ ✔ ✔ ✔ ✔ ✔ ...