关于跨域介绍和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. ...
随机推荐
- NumPy基础操作(2)
NumPy基础操作(2) (注:记得在文件开头导入import numpy as np) 目录: 写在前面 转置和轴对换 NumPy常用函数 写在前面 本篇博文主要讲解了普通转置array.T.轴对换 ...
- Tensorflow基本概念笔记
一.TensorFlow使用简单,部署快捷 TensorFlow使用数据流图(计算图)来规划计算流程,可以将计算映射到不同的硬件和操作平台.凭借着统一的架构,TensorFlow可以方便的部署剑各种平 ...
- golang 实现定时任务
在实际开发过程中,我们有时候需要编写一些定时任务.当然我们可以使用crontab命令实现我们的需求.但是这种方法不满足一些定制化场景,同时会依赖具体的操作系统环境. 定时任务 在golang中我们可以 ...
- spark 预编译安装
1.下载地址: http://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-3.0.0-preview/spark-3.0.0-preview-bin ...
- jvm问题排查工具、命令
dump生成:jmp -dump:live,format=b,file=/tmp/some.bin PID.其中,加上live表示只dump存活的对象. 线程栈信息生成:jstack PID > ...
- Sql CLR创建一个简单的表值函数
1.创建面目: 2. 添加函数代码: using System; using System.Data.Sql; using Microsoft.SqlServer.Server; using Syst ...
- Spring Cloud Alibaba学习笔记(18) - Spring Cloud Gateway 内置的过滤器工厂
参考:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-clou ...
- 关于梯度下降之前需要进行feature scale的记录
先上吴恩达老师的课件图 1.对于梯度下降而言,学习率很大程度上影响了模型收敛的速度.对于不同规模的特征,如果采用相同的学习率,那么如果学习率适应于scale大的数据,scale较小的数据由于学习率过大 ...
- elasticsearch*3 + Es-Head + kibana Docker集群
ES官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html 拉取docker镜像 dock ...
- Sqlite in flutter, how database assets work
First off, you will need to construct a sqlite database from your csv. This can be done in the follo ...