Luffy - 解决跨域问题
Luffy - 解决跨域问题
- 一:跨域请求
- 0. 跨域问题的出现
- 1.同源策略
- ① 简介
- 2. CORS(跨域资源共享)简介
- 3. `CORS`基本流程
- 4. 解决跨域问题的3种方法
- 5. `CORS`两种请求详解
- 6. 浏览器对这两种请求的处理,是不一样的
- 二:解决跨域问题(服务端)
- 【简单请求】
- 1. 原Django项目:`apps/user/views.py`
- 2. 原Django项目:`apps/user/urls.py`
- 3. 原Django项目:`dev.py`中注释掉`CSRF`
- 4. 再创建1个Django项目(用另外的端口)
- ① `templates`中创建`index.html`
- ② `views.py`
- ③ `urls.py`
- 【非简单请求】
- 原Django项目`apps/user/views.py`
- 新Django项目`templates/index.html`
- 【中间件处理】
- ① 在原Django项目的根路径创建`mymiddle.py` - 自定义中间件
- ② 在原Django项目的`dev.py`的中间件中添加自定义中间件
- ③ 原Django项目`apps/user/views`中替换成如下代码
- 三:解决跨域问题(第三方)
- 1. 后端配置
- ① 后端安装跨域模块
- ② 到`dev.py`中进行注册
- ③ 到`dev.py`中添加中间件
- ④ 到`dev.py`中添加如下代码
- ⑤ 设置`dev.py`的`ALLOWED_HOSTS`
- 2. 后端测试
- ① (测试 - 后台)到`apps/user/views`中替换成如下代码
- ② (测试 - 后台)到apps/user/urls中替换成如下代码
- ③ 启动项目
- ④ 访问测试
- 3. 前端测试
- ①(测试 - 前台)`App.vue` 中换成如下代码
- ② 启动项目
- 4. 测试效果
- 四:解决跨域问题(前端)
- 1. 前端`App.vue`
- 2. 前端项目根路径的`vue.config.js`
一:跨域请求
0. 跨域问题的出现
问题出现:前后端来自同一个IP
的不同端口
一种奇葩的解决方法:开发的时候前后端分离,部署的时候不分离
1.同源策略
① 简介
同源策略,是浏览器为了保护用户信息安全的一种安全机制
所谓的同源就是指代通信的两个地址(例如服务端接口地址与浏览器客户端页面地址)之间比较,是否协议、域名(IP)和端口相同
不同源的客户端脚本[
javascript
]在没有得到服务端的明确授权的情况下,浏览器会拒绝显示服务端信息提供给前端ajax/axios
前端地址:http://www.4399.com/index.html
|
是否同源 | 原因 |
---|---|---|
http://www.4399.com/user/login.html
|
是 | 协议、域名、端口相同 |
http://www.4399.com/about.html
|
是 | 协议、域名、端口相同 |
https://www.4399.com/user/login.html
|
否 | 协议不同 ( https和http ) |
http:/www.4399.com:5000/user/login.html
|
否 | 端口 不同( 5000和80) |
http://doc.4399.com/user/login.html
|
否 | 域名不同 ( doc和www ) |
http://www.4399.top/user/login.html
|
否 | 域名不同 ( com和top ) |
2. CORS(跨域资源共享)简介
CORS
是一个W3C
标准,全称是"跨域资源共享",它允许浏览器向跨源的后端服务器发出ajax
请求,从而克服了AJAX
只能同源使用的限制。
实现CORS
主要依靠后端服务器中响应数据中设置响应头信息返回的
CORS
需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10
。
整个
CORS
通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS
通信与同源的AJAX
通信没有差别,代码完全一样。浏览器一旦发现AJAX
请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现
CORS
通信的关键是服务器。只要服务器实现了CORS
接口,就可以跨源通信
容易混淆的点:
CORS
:跨域资源共享CSRF
:跨站请求伪造XSS
:跨站脚本攻击
3. CORS
基本流程
浏览器将CORS
请求分成两类:简单请求(simple request
)和非简单请求(not-so-simple request
)
- 浏览器发出
CORS
简单请求,只需要在头信息之中增加一个Origin
字段 - 浏览器发出
CORS
非简单请求,会在正式通信之前,增加一次HTTP
查询请求,称为”预检”请求(preflight
) - 览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些
HTTP
动词和头信息字段 - 只有得到肯定答复,浏览器才会发出正式的
XMLHttpRequest
请求,否则就报错。
4. 解决跨域问题的3种方法
- 前端解决(通过代理解决)
- 自己解决(自己写代码)
- 借助第三方模块(
django-cors-headers
)
5. CORS
两种请求详解
只要同时满足以下两大条件,就属于简单请求
① 请求方法是以下三种方法之一
HEAD
GET
POST
②
HTTP
的头信息不超出以下几种字段Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
:只限于三个值application/x-www-form-urlencoded
、multipart/form-data
、text/plain
凡是不同时满足上面两个条件,就属于非简单请求
6. 浏览器对这两种请求的处理,是不一样的
简单请求和非简单请求的区别
- 简单请求:发1次请求
- 非简单请求:发2次请求,在发送数据之前会先发1次请求用于做“预检”看后端是否允许,只有“预检”通过后才再发送1次请求用于数据传输。
请求方式:OPTIONS
预检:
- 检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
如何预检:
- 如果复杂请求是
PUT
等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
- 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
二:解决跨域问题(服务端)
【简单请求】
1. 原Django项目:apps/user/views.py
from django.http import JsonResponsedef test(request):obj = JsonResponse({'name': 'Darker', 'age': '18'})# 值针对简单请求obj['Access-Control-Allow-Origin'] = '*' # 允许所有IP访问return obj
2. 原Django项目:apps/user/urls.py
from django.urls import path
from user import viewsurlpatterns = [path('test/', views.test),
]
3. 原Django项目:dev.py
中注释掉CSRF
4. 再创建1个Django项目(用另外的端口)
① templates
中创建index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<button id="btn">点我</button></body>
<script>$('#btn').click(function () {$.ajax({url: 'http://127.0.0.1:8000/user/test/',method: 'get',success: function (data) {console.log(data)}})})
</script>
</html>
② views.py
from django.shortcuts import renderdef index(request):return render(request, 'index.html')
③ urls.py
from django.urls import path
from app01 import viewsurlpatterns = [path('test/', views.index),
]
【非简单请求】
原Django项目apps/user/views.py
from django.http import JsonResponsedef test(request):obj = JsonResponse({'name': 'Darker', 'age': '18'})if request.method == 'OPTIONS':obj['Access-Control-Allow-Headers'] = 'Content-Type,authorization' # 或者填写 *obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8002' # 8002端口是当前项目的return obj
新Django项目templates/index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<button id="btn">点我</button></body>
<script>$('#btn').click(function () {let obj = {name: 'Darker'}$.ajax({url: 'http://127.0.0.1:8000/user/test/',method: 'post',contentType: 'application/json',headers: {authorization: 'Darker'},data: JSON.stringify(obj),success: function (data) {console.log(data)}})})
</script>
</html>
【中间件处理】
① 在原Django项目的根路径创建mymiddle.py
- 自定义中间件
from django.utils.deprecation import MiddlewareMixinclass CoreMiddle(MiddlewareMixin):def process_response(self, request, response):if request.method == 'OPTIONS':response['Access-Control-Allow-Headers'] = 'Content-Type, authorization' # 如果是 * 就代表全部IP都可以访问response['Access-Control-Allow-Origin'] = '*'return response
② 在原Django项目的dev.py
的中间件中添加自定义中间件
MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','mymiddle.CoreMiddle', # 这一句'django.middleware.common.CommonMiddleware',# 'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]
③ 原Django项目apps/user/views
中替换成如下代码
from django.http import JsonResponsedef test(request):return JsonResponse({'name': 'Darker', 'age': '18'})
三:解决跨域问题(第三方)
1. 后端配置
① 后端安装跨域模块
pip install django-cors-headers
② 到dev.py
中进行注册
INSTALLED_APPS = (...'corsheaders'
)
③ 到dev.py
中添加中间件
MIDDLEWARE = [...'corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware', # 这个是原本就存在的...
]
④ 到dev.py
中添加如下代码
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = (
# 'http://127.0.0.1:8080',
# )
CORS_ALLOWED_ORIGINS_REGEXES=[r'^http://.*?$',
]
# CORS_ORIGIN_REGEXES_WHITELIST = (
# r'^http://.*?$',
# )
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',
)
⑤ 设置dev.py
的ALLOWED_HOSTS
ALLOWED_HOSTS = ['*']
2. 后端测试
① (测试 - 后台)到apps/user/views
中替换成如下代码
from django.http import JsonResponsedef test(request):return JsonResponse({'name': 'Darker', 'age': '18'})
② (测试 - 后台)到apps/user/urls中替换成如下代码
from django.urls import path
from user import viewsurlpatterns = [path('test/', views.test),
]
③ 启动项目
python manage.py runserver 127.0.0.1:8000
④ 访问测试
3. 前端测试
①(测试 - 前台)App.vue
中换成如下代码
<template><div id="app"><router-view/>{{name}}</div>
</template><script>
export default {data () {return {name: []}},mounted () {this.$axios.get(this.$settings.base_url + '/user/test/').then(res => {this.name = res.data})}
}
</script>
② 启动项目
npm run serve
4. 测试效果
四:解决跨域问题(前端)
1. 前端App.vue
<template><div id="home"><h1>我是主页</h1><h2>{{info}}</h2></div>
</template><script>
export default {name: 'Home',data () {return {info: []}},mounted () {this.$axios.get('/moreClassicList?sortId=1&showType=3').then(res => {console.log(res.data)})}
}
</script><style scoped></style>
2. 前端项目根路径的vue.config.js
const webpack = require("webpack");module.exports = {configureWebpack: {plugins: [new webpack.ProvidePlugin({$: "jquery",jQuery: "jquery","window.jQuery": "jquery","window.$": "jquery",Popper: ["popper.js", "default"]})]},devServer: {proxy: {'/ajax': {target: 'https://m.maoyan.com/',changeOrigin: true},'/user': {target: 'http://127.0.0.1:8000',changeOrigin: true}}}
};
Luffy - 解决跨域问题相关推荐
- 继承WebMvcConfigurer 和 WebMvcConfigurerAdapter类依然CORS报错? springboot 两种方式稳定解决跨域问题
继承WebMvcConfigurer 和 WebMvcConfigurerAdapter类依然CORS报错???springboot 两种方式稳定解决跨域问题! 之前我写了一篇文章,来解决CORS报错 ...
- CORS-跨域资源共享 解决跨域问题
1.什么是跨域? a.test.com 和 b.test.com 是两个不同的域,而处于安全机制考虑,JS只能访问与所在页面同一个域(相同协议.域名.端口)的内容,但是我们在项目开发时,经常遇到一个页 ...
- 前端解决跨域问题的8种方案(最新最全)
.同源策略如下: URL 说明 是否允许通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.j ...
- React Axios 请求解决跨域问题
网上看了很多的方案,但是不知道为什么,作为初学者,对react不太清楚的话,解决跨域还是有很多的问题.这篇博客针对小白,第一次调试react 跨域问题,甚至第一次使用Axios ,第一次... 废话就 ...
- iframe解决跨域ajax请求的方法
iframe跨域的基本前提是,一个页面可以嵌套非同源站点的html文件,以及某一个域名下的html页面可以通过脚本向同域名服务器发出ajax请求.当一个域名为domain1下的页面A想要向domain ...
- java 跨域_springboot解决跨域CROS问题,用注解@CrossOrigin
项目是springboot框架,前后端分离,需要跨域,当前前端可以用JSONP解决,但是java端如何解决呢? 因为是springboot框架,所以好多都可以用注解解决问题,所以就用到了@CrossO ...
- android ajax 跨域更新本地html,本地webapp是怎么解决跨域问题的?
像ionic的cli,都可以把一个ionic的webapp打包成本地的,那这样的话是如何解决跨域问题的? 在PC上,我直接访问连接获取数据,代码如下.(抄自W3School) function loa ...
- jsonp解决跨域问题
跨域 就是由于JavaScript同源策略的限制,使得a.com域名下的js无法操作b.com或c.a.com域名下的对象或数据. 简单理解同一个域就是:相同域名.相同端口.相同协议! JS部分(使用 ...
- axios请求接口http_Vue使用Axios实现http请求以及解决跨域问题
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.Axios的中文文档以及github地址如下: 中文:https://www.kancloud.cn/y ...
最新文章
- 黑帽SEO:Google为什么会屏蔽你的网站
- 知识图谱学习笔记-知识图谱介绍
- java nio.Buffer的属性变化
- [自爆系列]浅谈我对搜索的错误了解
- Jetson Nano安装pytorch 基于torch1.6和torchvision0.7
- BootStrap的入门和响应式的使用
- 万字长文:解读区块链7类共识算法
- spring boot controller 初始化_基于 tyboot 快速初始化 springboot 单体项目
- 架构师要了解那些??
- Android 四大组件学习之ContentProvider四
- java 验证是否为省份证号 详细验证 验证月份 日期等 要素
- 使用wps把word格式文件转换成pdf文件
- 2009年25大最新网络游戏排行榜
- scrapy15.0,scrapy.contrib.downloadermiddleware.useragent` is deprecated,旧模块被弃用解决办法.
- a10 amd 安装黑苹果_黑苹果整合版系统U盘镜像Niresh macOS Sierra 10.12.3 支持Intel/AMD......
- Me-tetrazine-Disulfo-Cyanine5,甲基四嗪-磺酸基菁染料Cy5,蓝色固体
- 计算机网络知识点————交换机
- 如何彻底关闭windows10自动更新,禁用Windows Update
- python字典操作题_python字典练习题
- 向量、矩阵乘法的几何意义(二) 矩阵乘法(Matrix Multiplication)