目录
跨域请求
跨域是指浏览器不能执行其他网站的脚本, 它是由浏览器的同源策略造成的,,是浏览器对javascript 实施的安全限制。
浏览器从一个域名的网页请求去另一个域名的资源时,出现域名,端口,协议任意一个不同就属于跨域
部署时前后端不分离可以解决此问题【但是不推荐】
同源策略
同源策略是浏览器为了保护用户信息安全的一种安全政策。 指的是iu篮球页面的协议, 域名,端口号都相同,其目的是为了保证用户的信息安全,防止恶意网站盗取数据信息。
不同源的客户端脚本js在没有得到服务端的明确授权的情况下,浏览器会显示拒绝提供服务给前端ajax/axios。
CORS(跨域资源共享)简介
CORS是一个W3C标准,全程跨域资源共享。 它允许浏览器向跨源的后端服务器发出ajax请求,
从而克服了AJAX只能同源使用的限制。
实现CORS主要一开后端服务器响应数据中设置响应头信息返回的CORS需要浏览器和服务器同时支持, 目前除了IE浏览器都支持该功能
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信
容易混淆的点:
- CORS:跨域资源共享
- CSRF: 跨站请求伪造
- XSS: 跨站脚本攻击
CORS基本流程
浏览器讲CORS请求分成两类: 简单请求(simple request) 和 非简单请求(not-so-simple-request)
浏览器发出CORS简单请求只需要在头信息中增加Origin字段
浏览器发出非简单CORS请求, 会在正式通信之前增加一次Http查询请求,即’预检‘请求。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之内,以及跨源使用那些Http动词和头信息字段
只有的带肯定答复,溜啦冷凝器才会发出正式的XMLHttpRequest请求,否则就会报错。
解决跨域问题的方法
前端: 通过代理解决
nginx代理
cors解决跨域:django-cors-headers
CORS两种请求详解
只需要同时满足一下两大条件,就属于简单请求
1. 请求方式是一下三种
- HEAD
- GET
- POST
2, Http的头部信息不能超出以下几种字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不能同时满足以上两个条件就属于非简单请求
json格式是非简单请求
浏览器对这两种请求的处理是不一样的
简单请求和非简单请求的区别
简单请求:之发送一次请求
非简单请求: 发送2次请求,在发送数据之前会先发一次请求用于做’预检‘看后端是否允许,只有预检通过之后才会再次发送请求用于数据传输
请求方式OPTIONS
预检:
如果非简单请求是PUT等请求, 则服务端需要设置允许某请求,否则预检不通过
- Access-Control-Request-Method
如果非简单请求设置了请求头, 则服务端需要设置允许某请求头,否则预检不通过
- Access-Control-Request-Headers
解决跨域问题(服务端)
简单请求
Django项目: apps/user/views.py
from django.http import JsonResponse
def 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 views
urlpatterns = [
path('test/', views.test),
]
3. django项目中注释掉dev.py中的CSRF
4, 再创建一个django项目(用另一个端口)
template中创建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 render
def index(request):
return render(request, 'index.html')
urls.py
from django.urls import path
from app01 import views
urlpatterns = [
path('test/', views.index),
]
非简单请求
原django项目 app/user/view.py
from django.http import JsonResponse
def 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项目中 template/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>
3, 中间件处理
① 在原Django项目的根路径创建mymiddle.py
- 自定义中间件
from django.utils.deprecation import MiddlewareMixin
class 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 JsonResponse
def test(request):
return JsonResponse({'name': 'Darker', 'age': '18'})
解决跨域问题(第三方)
后端配置
① 后端安装跨域模块
pip install django-cors-headers
2, 到dev.py中注册
INSTALLED_APPS = (
...
'corsheaders'
)
3 到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 = ['*']
后端测试
(测试 - 后台)到apps/user/views
中替换成如下代码
from django.http import JsonResponse
def test(request):
return JsonResponse({'name': 'Darker', 'age': '18'})
(测试 - 后台)到apps/user/urls
中替换成如下代码
from django.urls import path
from user import views
urlpatterns = [
path('test/', views.test),
]
启动项目
python manage.py runserver 127.0.0.1:8000
访问测试
前端测试
(测试 - 前台)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
解决跨域问题(前端)
前端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>
前端项目根路径 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
}
}
}
};
wsgi,uWSGI,uwsgi
https://www.liuqingzheng.top/article/1/05-CGI,FastCGI,WSGI,uWSGI,uwsgi%E4%B8%80%E6%96%87%E6%90%9E%E6%87%82/