前后台分离跨域交互
目录
一、跨域问题详解
以后只要前后端分离项目,都会出现跨域问题,咱们要解决。
1.1 同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
请求的url地址,必须与浏览器上的url地址处于同域上:也就是[域名],[端口],[协议]相同。
http://127.0.0.1:8080
ftf://127.0.0.1:8080
比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据,浏览器上就会报错,这个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险。
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')
请求发送,服务的执行,数据也正常返回,只是被浏览器拦截了。
正因为同源策略的存在,咱们写前后端分离的项目,无法正常获取到数据。
1.2 解决跨域问题:
1. jsonp 跨域(不了解)
2. 跨域资源共享(CORS) 后端技术
3. Nginx代理
二、CORS:跨域资源共享
CORS需要浏览器和服务器同时支持,所有浏览器都支持该功能。
只需要服务的处理即可:只需要在在响应头中加入固定的头就实现cors ---> 比如在响应头中加入Access-Control-Allow-Origin='*' ---> get请求就没有跨域了 ---> 但是put请求还会有。
- cors的请求分两种
- 简单请求,浏览器直接发起
- 非简单请求,浏览器先发送要给options预检请求,服务端允许,再发送真正的请求
2.1 什么是简单请求,什么是非简单请求?
只要同时满足以下两大条件,就属于简单请求。
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
凡是不同时满足上面两个条件,就属于非简单请求。
2.2 支持跨域
支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’
支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
2.3 解决跨域
# 使用cors解决跨域,就是再响应头中加入固定的一些东西,专门写个中间件
res['Access-Control-Allow-Headers'] = 'token'
res['Access-Control-Allow-Methods'] = 'DELETE'
res['Access-Control-Allow-Origin'] = 'http://192.168.1.252:8080'
三、自定义中间件,解决跨域问题
common_mideleware.py
from django.utils.deprecation import MiddlewareMixin
自定义中间件
### 自定义中间件解决跨域问题 ---> 以后其它框架都是这个原理 ---> django上有人做了
class CorsMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if request.method == 'OPTIONS':
response['Access-Control-Allow-Headers'] = 'token'
response['Access-Control-Allow-Methods'] = 'DELETE'
response['Access-Control-Allow-Origin'] = '*'
return response
配置文件
### 配置文件配置中间件
MIDDLEWARE = [
'utils.common_mideleware.CorsMiddleware'
]
四、django使用django-cors-headers解决跨域问题
4.1 使用pip安装
pip install django-cors-headers
4.2 添加到setting的app中
INSTALLED_APPS = (
...
'corsheaders',
...
)
4.3 添加中间件
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
4.4 setting下面添加下面的配置
CORS_ORIGIN_ALLOW_ALL = True
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',
'token' # 后期根据自己的请求头再加
)
五、django-cors-headers源码
# 核心代码再中间件的 ---> process_response 3.0.14 版本
class CorsMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if (
not conf.CORS_ALLOW_ALL_ORIGINS
and not self.origin_found_in_white_lists(origin, url)
and not self.check_signal(request)
):
return response
if conf.CORS_ALLOW_ALL_ORIGINS and not conf.CORS_ALLOW_CREDENTIALS:
response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*"
else:
response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin
if request.method == "OPTIONS":
response[ACCESS_CONTROL_ALLOW_HEADERS] = ", ".join(conf.CORS_ALLOW_HEADERS)
response[ACCESS_CONTROL_ALLOW_METHODS] = ", ".join(conf.CORS_ALLOW_METHODS)
return response