一、为什么会有跨域问题?

是因为浏览器的同源策略是对ajax请求进行阻拦了,但是不是所有的请求都给做跨域,对href属性都不拦截。

二、解决跨域问题的两种方式

三、JSONP

先简单来说一下JSONP,具体详细详见上面JSONP

JSONP是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。(创建一个回调函数,然后在远程服务上调用这个函数并且将json数据形式作为参数传递,完成回调)。

四、CORS跨域

随着技术的发展,现在的浏览器可以主动支持设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。

1、简单请求和复杂请求

条件:
1、请求方式:HEAD、GET、POST
2、请求头信息:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type 对应的值是以下三个中的任意一个
application/x-www-form-urlencoded
multipart/form-data
text/plain 注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求

2、简单请求和复杂请求的区别

简单请求:一次请求

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

3、关于预检

在发送真正的请求之前,会默认发送一个options请求,做预检,预检成功后才发送真正的请求

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

4、CORS的优缺点

  • CORS的优点:可以发任意请求
  • CORS的缺点:上是复杂请求的时候得先做个预检,再发真实的请求。发了两次请求会有性能上的损耗

五、JSONP和CORS的区别

JSONP:服务端不用修改,需要改前端。发jsonp请求

JSONP:只能发GET请求

CORS:前端的代码不用修改,服务端的代码需要修改。如果是简单请求的话在服务端加上一个响应头。

CORS:可以发任意请求

六、基于CORS实现ajax请求

1、支持跨域,简单请求

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

客户端

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width">
<title>Title</title>
</head>
<body>
<div>
<h1>欢迎来到我的主页</h1>
<button onclick="getData()">获取用户数据</button>
</div>
<script src="/static/jquery-1.12.4.min.js"></script>
<script>
function getData() {
$.ajax({
url:'http://127.0.0.1:8080/index/',
type:"GET",
success:function (data) {
console.log(data)
} })
}
</script>
</body>
</html>

index.html

服务端

 from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.views import APIView # Create your views here.
class IndexView(APIView):
def get(self,request,*args,**kwargs):
ret = {
'code': 111,
'data': '你好吗?'
}
response = JsonResponse(ret)
response['Access-Control-Allow-Origin'] = "*"
return response

views.py

2、支持跨域,复杂请求

如果是复杂请求在你真正的发请求之前,会先偷偷的发一个OPTION请求,先预检一下,我

允许你来你才来

如果想预检通过就得写个option请求

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width">
<title>Title</title>
</head>
<body>
<input type="button" value="获取用户数据" onclick="getUser()">
<script src="/static/jquery-1.12.4.min.js"></script>
<script>
function getUser() {
$.ajax({
url:'http://127.0.0.1:8080/user/',
type:'POST',
data:{'k1':'v1'},
headers:{
'h1':'sdfdgfdg'
},
success:function (ret) {
console.log(ret)
}
})
}
</script>
</body>
</html>

user.html

 from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView class UserIndex(APIView):
def get(self,request,*args,**kwargs):
ret = {
'code': 111,
'data': '你好吗?'
}
response = JsonResponse(ret)
response['Access-Control-Allow-Origin'] = "*"
return response def post(self,request,*args,**kwargs):
print(request.POST.get('k1'))
ret = {
'code':1000,
'data':'过年啦',
}
response = JsonResponse(ret)
response['Access-Control-Allow-Origin'] = "*"
return response def options(self, request, *args, **kwargs):
# self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
# self.set_header('Access-Control-Allow-Headers', "k1,k2")
# self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
# self.set_header('Access-Control-Max-Age', 10) response = HttpResponse()
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Headers'] = 'h1'
# response['Access-Control-Allow-Methods'] = 'PUT'
return response

服务端

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

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

3、跨域获取响应头

默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要再服务器端设置Access-Control-Expose-Headers。

 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body> <p>
<input type="submit" onclick="XmlSendRequest();" />
</p> <p>
<input type="submit" onclick="JqSendRequest();" />
</p> <script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
// 获取响应头
console.log(xhr.getAllResponseHeaders());
}
};
xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
} function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
// 获取响应头
console.log(xmlHttpRequest.getAllResponseHeaders());
}
})
} </script>
</body>
</html> HTML

HTML

 class MainHandler(tornado.web.RequestHandler):

     def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com") self.set_header('xxoo', "seven")
self.set_header('bili', "daobidao") self.set_header('Access-Control-Expose-Headers', "xxoo,bili") self.write('{"status": true, "data": "seven"}') def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10) Tornado

Tornado

4、跨域传输cookie

在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。

如果想要发送:

  • 浏览器端:XMLHttpRequest的withCredentials为true
  • 服务器端:Access-Control-Allow-Credentials为true
  • 注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 *
 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body> <p>
<input type="submit" onclick="XmlSendRequest();" />
</p> <p>
<input type="submit" onclick="JqSendRequest();" />
</p> <script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
}
}; xhr.withCredentials = true; xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
} function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
xhrFields:{withCredentials: true},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
} </script>
</body>
</html> HTML

HTML

 class MainHandler(tornado.web.RequestHandler):

     def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Credentials', "true") self.set_header('xxoo', "seven")
self.set_header('bili', "daobidao")
self.set_header('Access-Control-Expose-Headers', "xxoo,bili") self.set_cookie('kkkkk', 'vvvvv'); self.write('{"status": true, "data": "seven"}') def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10)

Tornado

JSONP、CORS解决跨域问题的更多相关文章

  1. Django使用jsonp和cors解决跨域请求问题

    1.使用jsonp的方式解决跨域请求的问题 我启动两个django项目,然后使用的端口不一样,在项目1中通过ajax发请求给项目2,然后接受项目2发送过来的数据 先看项目1的ajax的代码 $(&qu ...

  2. 一步一步学习SignalR进行实时通信_3_通过CORS解决跨域

    原文:一步一步学习SignalR进行实时通信_3_通过CORS解决跨域 一步一步学习SignalR进行实时通信\_3_通过CORS解决跨域 SignalR 一步一步学习SignalR进行实时通信_3_ ...

  3. Spring Boot中通过CORS解决跨域问题

    今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由Netscap ...

  4. 配置CORS解决跨域调用—反思思考问题的方式

    导读:最近都在用一套完整的Java EE的体系做系统,之前都是用spring框架,现在弄这个Java EE,觉得新鲜又刺激.但,由于之前没有过多的研究和使用,在应用的过程中,也出现了不少的问题.累积了 ...

  5. Spring Boot2 系列教程(十四)CORS 解决跨域问题

    今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netsca ...

  6. 14 微服务电商【黑马乐优商城】:day06-使用nginx反向代理并掌握cors解决跨域

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  7. 使用cors解决跨域遇到浏览器发出options嗅探

    前言: 本地开发起的服务器,通过修改hosts文件设置域名映射到本地,接口在测试环境 1. 服务器端设置cors, 配置access-control-allow-origin 头部 使用蚂蚁金服的up ...

  8. 服务端 CORS 解决跨域

    当协议.域名.端口中任一个不同时产生跨域 CORS 跨域资源共享(Cross-origin resource sharing) 参考资料https://developer.mozilla.org/zh ...

  9. 后端CORS解决跨域问题

    一 . 为什么会有跨域问题 是因为浏览器的同源策略是对ajax请求进行阻拦了,但是不是所有的请求都给做跨域,像是一般的href 属性,a标签什么的都不拦截. 二 . 解决跨域的方法 解决跨域有两种方法 ...

随机推荐

  1. 开发一个根据xml创建代理类的小框架

    github地址 https://github.com/1367356/GradleTestUseSubModule/tree/master/CreateMyFrameWork 1:定义一些规则

  2. Centos7使用yum下载rpm包而不执行安装

    yum-downloadonly是yum的一个插件,使得yum可以从RHN或者yum的仓库只下载包而不安装. 举例,从yum源下载ricci软件包 # yum install --downloadon ...

  3. PAT 1043 Is It a Binary Search Tree[二叉树][难]

    1043 Is It a Binary Search Tree(25 分) A Binary Search Tree (BST) is recursively defined as a binary ...

  4. Sparsity稀疏编码(三)

    稀疏编码(sparse coding)和低秩矩阵(low rank)的区别        上两个小结介绍了稀疏编码的生命科学解释,也给出一些稀疏编码模型的原型(比如LASSO),稀疏编码之前的探讨文章 ...

  5. 20165324_mybash

    20165324_mybash 实验要求 实验要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客(包含代码托管链接) 背景 ...

  6. 如何使用代码备份SQL Server数据库

    1.添加引用 using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Common; 2. Bac ...

  7. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  8. fedora修改主目录文件名为英文

           在gnome-terminal里面能够显示中文的,但是在文本终端里面中文都是不能显示的,是一个小小的正方形.因此可以只把主目录文件名换成英文的,方便文本终端命令输入,而其他的一些地方还是 ...

  9. STM32端口输入输出模式配置

    STM32的IO口模式配置 根据数据手册提供的信息,stm32的io口一共有八种模式,他们分别是: 四种输入模式 上拉输入:通过内部的上拉电阻将一个不确定的信号通过一个电阻拉到高电平. 下拉输入:把电 ...

  10. POJ 2195 Going Home(最小费用最大流)题解

    题意:给你一张图,有k个人和k个房子,每个房子只能住一个人,每个人到某一房子的花费为曼哈顿距离,问你让k个人怎么走,使他们都住房子且花费最小. 思路:我们把所有人和超级源点相连,流量为1花费为0,所有 ...