中间件的使用一(设置跨域访问)

一、关于跨域的认识

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

何为所谓同源:

  • 1、相同的协议(httphttps)
  • 2、相同的域名、或者主机ip
  • 3、相同的端口号

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

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

  • 制约: XmlHttpRequest
  • 不制约: imgiframescript等具有src属性的标签

二、关于常见解决跨域的方式

  • 1、前端出现跨域的问题报错如下

    Failed to load http://localhost:9000/test1/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63343' is therefore not allowed access.
    
  • 2、jsonp原理

    利用script标签的src属性(浏览器允许script标签跨域),利用js脚本动态的在头部引入跨域的地址,主要不足:只能是get请求,不能是post等别的请求

    // 方法一、动态的添加跨域地址
    function Jsonp1(){
      var tag = document.createElement('script');
      tag.src = "http://c2.com:8000/test/";
      document.head.appendChild(tag);
      document.head.removeChild(tag);
    }
    
    function Jsonp2(){
      $.ajax({
        url: "http://c2.com:8000/test/",
        type: 'GET',
        dataType: 'JSONP',
        success: function(data, statusText, xmlHttpRequest){
          console.log(data);
        }
      })
    }
    
  • 3、CORS设置浏览器允许跨域请求,其本质是设置请求响应头,使浏览器允许跨域请求(主要工作是后端设置)。

  • 4、更多的跨域请求请参考

三、关于简单请求与非简单请求

  • 1、满足简单请求的条件(需要同时满足)

    • 1.请求方式:HEADGETPOST
    • 2.请求头信息: Content-Type对应其中任意一个(application/x-www-form-urlencoded, multipart/form-data, text/plain)
  • 2、简单请求与非简单请求的区别

    • 1.简单请求只请求一次
    • 2.非简单请求,在发送数据之前会先进行一次预检,只有预检通过后才能再发送一次请求用于数据传输.
  • 3、关于预检的认识

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

四、使用中间件实现跨域访问

  • 1、导包

    from django.utils.deprecation import MiddlewareMixin
    
  • 2、定义中间件

    class CORSMiddleWare(MiddlewareMixin):
        """
        设置跨域的中间件
        """
    
        def process_response(self, request, response):
            # 添加请求头
            # 允许你的域名来获取数据(也可以指定域名)
            response['Access-Control-Allow-Origin'] = '*'
    
            if request.method == 'OPTIONS':
                # 允许你携带Content-Type请求头,也可以设置别的自定义字段(不设置客户端设置的就不能通过预检)
                response['Access-Control-Allow-Headers'] = 'Content-Type,k1, k2'
    
                # 允许你发送DELETE,PUT的请求方式
                response['Access-Control-Allow-Methods'] = 'DELETE,PUT'
    
                # 允许设置缓存时间
                response['Access-Control-Max-Age'] = 20
    
            return response
    
  • 3、注册

    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',
        'middle.cors_middle_ware.CORSMiddleWare',  # 自定义跨域中间件
    ]
    
  • 4、客户端测试

    $('#btn').on('click', function () {
      $.ajax({
        url: 'http://localhost:9000/test1/',
        method: 'post',
        data: {
          username: $('#name').val()
        },
        headers: {
          'k1': 'hello'
        },
        success: function (data) {
          console.log(data)
        }
      })
    })
    

五、补充说明,使用django-cors-headers插件来实现跨域访问

results matching ""

    No results matching ""