django处理跨域

  django处理Ajax跨域访问时使用javascript进行ajax访问的时候,出现如下错误

这里写图片描述

出错原因:javascript处于安全考虑,不允许跨域访问。下图是对跨域访问的解释:

概念

  这里说的js跨域是指通过js或python在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(Django)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

        跨域,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。这显然是不安全的。为此,浏览器的鼻祖:网景(Netscape)公司提出了优秀的解决方案:著名的浏览器同源策略。现在所有支持JavaScript的浏览器都会使用这个策略。

       同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略,它是由Netscape提出的一个著名的安全策略。

        所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

解决办法

1. 修改views.py文件

修改views.py中对应API的实现函数,允许其他域通过Ajax请求数据:

todo_list = [
    {"id": "1", "content": "吃饭"},
    {"id": "2", "content": "吃饭"},
]


class Query(View):
    @staticmethod
    def get(request):
        response = JsonResponse(todo_list, safe=False)
        response["Access-Control-Allow-Origin"] = "*"   
        response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
        response["Access-Control-Max-Age"] = "1000"
        response["Access-Control-Allow-Headers"] = "*"
        return response

    @staticmethod
    def post(request):
        print(request.POST)
        return HttpResponse()
  • 简单请求 OR 非简单请求 
    条件: 
        1、请求方式:HEAD、GET、POST 
        2、请求头信息: 
            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="PUT" 
            如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过 
            Access-Control-Request-Headers="k1"
  • 基于cors实现的ajax请求:

    1、支持跨域的简单请求

      服务器设置响应头:Access-Control-Allow-Origin = '指定域名' 

      服务器设置响应头:Access-Control-Allow-Origin = '*'    # *:表示允许所有的请求

    2、复杂请求的请求头:

      由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。   # 预检时可以发送空数据

      “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method="PUT"    # 或其他复杂请求如DELETE

      “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers="k1"     # ajax的header:{"k1":"v1"}

      “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age=10   # 十秒内此请求再有请求过来时无需再发送options预检,直接发送复杂请求,减轻服务器压力

    3、跨域获取响应头

      默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要再服务器端设置Access-Control-Expose-Headers。

    4、跨域传输cookie

      在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。

      如果想要发送:

        浏览器端:XMLHttpRequest的withCredentials为true

        服务器端:Access-Control-Allow-Credentials为true

    注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 


 

2. 添加中间件 django-cors-headers

GitHub地址: https://github.com/ottoyiu/django-cors-headers

2.1. 安装

 pip install django-cors-headers

2.2 添加app

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

2.3 添加中间件

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

2.4 配置允许跨站访问本站的地址

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = ( 'localhost:63343', )

# 默认值是全部:

CORS_ORIGIN_WHITELIST = ()  # 或者定义允许的匹配路径正则表达式.

CORS_ORIGIN_REGEX_WHITELIST = ('^(https?://)?(\w+.)?>google.com$', )   # 默认值:

CORS_ORIGIN_REGEX_WHITELIST = ()

2.5 设置允许访问的方法

CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
)

2.6 设置允许的header:

默认值:

CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)

  django处理Ajax跨域访问时使用javascript进行ajax访问的时候,出现如下错误

这里写图片描述

出错原因:javascript处于安全考虑,不允许跨域访问。下图是对跨域访问的解释:

概念

  这里说的js跨域是指通过js或python在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(Django)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

        跨域,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。这显然是不安全的。为此,浏览器的鼻祖:网景(Netscape)公司提出了优秀的解决方案:著名的浏览器同源策略。现在所有支持JavaScript的浏览器都会使用这个策略。

       同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略,它是由Netscape提出的一个著名的安全策略。

        所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

解决办法

1. 修改views.py文件

修改views.py中对应API的实现函数,允许其他域通过Ajax请求数据:

todo_list = [
    {"id": "1", "content": "吃饭"},
    {"id": "2", "content": "吃饭"},
]


class Query(View):
    @staticmethod
    def get(request):
        response = JsonResponse(todo_list, safe=False)
        response["Access-Control-Allow-Origin"] = "*"   
        response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
        response["Access-Control-Max-Age"] = "1000"
        response["Access-Control-Allow-Headers"] = "*"
        return response

    @staticmethod
    def post(request):
        print(request.POST)
        return HttpResponse()
  • 简单请求 OR 非简单请求 
    条件: 
        1、请求方式:HEAD、GET、POST 
        2、请求头信息: 
            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="PUT" 
            如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过 
            Access-Control-Request-Headers="k1"
  • 基于cors实现的ajax请求:

    1、支持跨域的简单请求

      服务器设置响应头:Access-Control-Allow-Origin = '指定域名' 

      服务器设置响应头:Access-Control-Allow-Origin = '*'    # *:表示允许所有的请求

    2、复杂请求的请求头:

      由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。   # 预检时可以发送空数据

      “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method="PUT"    # 或其他复杂请求如DELETE

      “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers="k1"     # ajax的header:{"k1":"v1"}

      “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age=10   # 十秒内此请求再有请求过来时无需再发送options预检,直接发送复杂请求,减轻服务器压力

    3、跨域获取响应头

      默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要再服务器端设置Access-Control-Expose-Headers。

    4、跨域传输cookie

      在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。

      如果想要发送:

        浏览器端:XMLHttpRequest的withCredentials为true

        服务器端:Access-Control-Allow-Credentials为true

    注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 


 

2. 添加中间件 django-cors-headers

GitHub地址: https://github.com/ottoyiu/django-cors-headers

2.1. 安装

 pip install django-cors-headers

2.2 添加app

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

2.3 添加中间件

MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

2.4 配置允许跨站访问本站的地址

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = ( 'localhost:63343', )

# 默认值是全部:

CORS_ORIGIN_WHITELIST = ()  # 或者定义允许的匹配路径正则表达式.

CORS_ORIGIN_REGEX_WHITELIST = ('^(https?://)?(\w+.)?>google.com$', )   # 默认值:

CORS_ORIGIN_REGEX_WHITELIST = ()

2.5 设置允许访问的方法

CORS_ALLOW_METHODS = (
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'OPTIONS'
)

2.6 设置允许的header:

默认值:

CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)

猜你喜欢

转载自www.cnblogs.com/95lyj/p/9440169.html