跨域请求

一、同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据
浏览器上就会报错,个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险

如果跨域发送请求,会出错

已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/index/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

1)举例,前端模板代码编写(get简单请求)

http://127.0.0.1:8000/test

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>Title</title>
</head>
<body>
<button id="btn">点我向http://127.0.0.1:8001/发请求</button>
</body>
<script>
    $("#btn").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8001/index/',
            type:'get',
            success:function (data) {
                alert(data)
            }
        })
    })
</script>
</html>
test.html

直接向http://127.0.0.1:8001/index发送请求,获取http://127.0.0.1:8001/index数据

def index(request):
    return HttpResponse('ok')
8001/index

 2) 解决该问题,需要在被请求的服务器允许其他服务器的请求

def index(request):
    obj=HttpResponse('ok')
    # obj['Access-Control-Allow-Origin'] = '*'  # 允许任意请求
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1://8000'
    return obj
8000/index

 二、跨域问题的简单请求和非简单请求

* 简单请求和非简单请求的区别?

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

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

1) 示例 将前端改为put请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>Title</title>
</head>
<body>
<button id="btn">点我向http://127.0.0.1:8001/发请求</button>
</body>
<script>
    $("#btn").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8001/index/',
            type:'put',
            success:function (data) {
                alert(data)
            }
        })
    })
</script>
</html>
test.html

处理该问题:    obj['Access-Control-Allow-Methods'] = 'put'

def index(request):
    obj=HttpResponse('ok')
    if request.method == 'OPTIONS':
        obj['Access-Control-Allow-Methods'] = 'PUT'
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000'
    return obj
8001/index

测试的时候,需要注释掉csrf的中间件

2)支持的数据格式

   Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

3)发送数据时的跨域问题。contentType:'application/json'

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>Title</title>
</head>
<body>
<button id="btn">点我向http://127.0.0.1:8001/发请求</button>
</body>
<script>
    $("#btn").click(function () {
        $.ajax({
            url:'http://127.0.0.1:8001/index/',
            type:'put',
            contentType:'application/json',
            data:'{"name":"user"}',
            success:function (data) {
                alert(data)
            }
        })
    })
</script>
</html>
test.html

被请求的服务器视图函数编写

def index(request):
    obj=HttpResponse('ok')
    if request.method == 'OPTIONS':
        obj['Access-Control-Allow-Methods'] = 'PUT'
        obj['Access-Control-Allow-Headers'] = '*'
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8000'
    return obj
8001/index

 三、跨域请求全局处理

1)创建一个中间件

from django.utils.deprecation import MiddlewareMixin
class Mymiddleware(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method == 'OPTIONS':
            response['Access-Control-Allow-Methods'] = 'PUT'
            response['Access-Control-Allow-Headers'] = '*'

        response['Access-Control-Allow-Origin'] = '*'
        return response
mymiddel.py

2)settings中导入该中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'app01.mymiddel.Mymiddleware'   # 导入内容
]
setting

3)视图函数就变的和以前一样了。

def index(request):
    obj=HttpResponse('ok')
    return obj
View Code
原文地址:https://www.cnblogs.com/linu/p/10123164.html