这是我参与8月更文挑战的第24天,活动详情查看: 8月更文挑战
微信公众号搜索 程序媛小庄 人生苦短 一起学Python
同源策略
同源策略:
它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现,是浏览器对访问到的结果进行了拦截。
请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据
浏览器上就会报错,这个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险。
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。
跨域资源共享
跨域资源共享
允许不同的域来我的服务器拿数据
跨域问题
我的服务器返回数据给其他域,被浏览器拦截
跨域请求分类
- 简单请求
只要同时满足以下两大条件,就属于简单请求
(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
-
非简单请求:凡是不同时满足上面两个条件,就属于非简单请求。
-
简单请求与非简单请求的区别
简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检”
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
解决跨域问题
跨域问题
举例说明:127.0.0.1:8002向127.0.0.1:8000发送请求,后者会返回数据给前者,但是在前者的浏览器被拦截
Access to XMLHttpRequest at 'http://127.0.0.1:8000/get/' from origin 'http://127.0.0.1:8002' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
简单请求跨域问题解决方案
- 解决方案:
由于在浏览器中的报错信息提示:No 'Access-Control-Allow-Origin' header is present on the requested resource.因此需要为服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’
代码示例:
# 被访问的服务端的视图类代码
from rest_framework.views import APIView
from rest_framework.response import Response
class TestView(APIView):
def get(self,request):
print('xxxx')
# 需要在被访问的服务端的response对象中加入'Access-Control-Allow-Origin':'http://127.0.0.1:8002',意思就是当我向http://127.0.0.1:8002发送数据时,对方浏览器允许接收我的数据
return Response('ok',headers={'Access-Control-Allow-Origin':'http://127.0.0.1:8002'})
def post(self,request):
print(111111111)
return Response('ok',headers={'Access-Control-Allow-Origin':'http://127.0.0.1:8002'})
# 返送ajax请求的前端页面代码及视图函数
def index(request):
response = render(request,'index.html')
return response
# 前端代码
<body>
<button id="btn">click me</button>
<script>
$('#btn').click(function () {
$.ajax({
url:'http://127.0.0.1:8000/get/',
type:'get',
success:function (data) {
console.log(data);
}
})
})
</script>
</body>
非简单请求解决方案
代码实例:
前端页面发送ajax请求,请方式是post,并且携带了json格式数据,属于非简单请求。
非简单请求会发送两次请求,第一是预检请求options,第二次是post请求。
简单请求只需要允许域名即可,非简单请求还需要允许['Access-Control-Allow-Headers'] = 'Content-Type'
- 总结:使用自定义中间件解决跨域请求问题
将中间件配置到配置文件中即可,在视图函数中就不需要单独配置了。
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
def process_response(self,request,response):
response['Access-Control-Allow-Origin'] = '*'
if request.method == 'OPTIONS':
response['Access-Control-Allow-Headers'] = 'Content-Type'
return response
第三方插件解决跨域问题 django-cors-headers
- 安装
pip install django-cors-headers
- 添加到settings的app中
INSTALLED_APPS = (
...
'corsheaders',
...
)
- 添加到中间件中
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
- settings.py中配置如下代码
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',
)
结语
文章首发于微信公众号程序媛小庄,同步于掘金。
码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)