首页 > 技术文章 > 跨域问题cors

chvv 2018-10-19 10:08 原文

本质设置响应头

由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。

特别的:由于同源策略是浏览器的限制,所以请求的发送和响应是可以进行,只不过浏览器不接受罢了。

浏览器同源策略并不是对所有的请求均制约:

  • 制约: XmlHttpRequest
  • 不叼: img、iframe、script等具有src属性的标签

跨域,跨域名访问,如:http://www.c1.com 域名向 http://www.c2.com域名发送请求。

1、JSONP实现跨域请求

JSONP(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性(浏览器允许script标签跨域)

2、CORS

随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。

* 简单请求 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
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求

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

  简单请求:一次请求

  非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
如果是复杂请求,先预检,通过之后才能发送POST请求
* 关于“预检”
  - 请求方式:OPTIONS
  - “预检”其实做检查来允许请求头或者method,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
  - 如何“预检”
     => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
     => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers

 cors.py 跨域中间件

from django.middleware.common import MiddlewareMixin

class CORSMiddleware(MiddlewareMixin):
    def process_response(self,request,response):
        #添加响应头
        # response['aaa'] = 6666
        # #允许你的域名来获取我的数据
        # response['Access-Control-Allow-Origin'] = '*'
        # #允许携带请求头Content-Type
        # response['Access-Control-Allow-Headers'] = 'Content-Type,xxxx,88888'
        # #允许发送DELETE,PUT
        # response['Access-Control-Allow-Methods'] = 'DELETE,PUT'
        response['Access-Control-Allow-Origin'] = '*'

        if request.method == "OPTIONS":
            response['Access-Control-Allow-Headers'] = "Content-Type"
            response['Access-Control-Allow-Methods'] = "PUT,DELETE"
        return response

settings.py的中间件中添加跨域中间件

MIDDLEWARE = [
    'api.cors.CORSMiddleware',
]

 

推荐阅读