zoukankan      html  css  js  c++  java
  • 跨域问题

    content-type    描述前端发送的数据格式

    推荐博客:https://blog.csdn.net/danielzhou888/article/details/72861097
    简单请求
    http : HEAD GET POST
    Content-Type只能是下列类型中的一个
        application/x-www-from-urlencoded       form表单请求
        multipart/form-data       需要在表单中进行文件上传时,就需要使用该格式
        text/plain                纯文本格式 
    复杂请求
    只要不满足简单请求都是复杂请求
    复杂请求先发送预检 OPTIONS
    

      

    利用中间件加响应头解决跨域

    # 中间件:
    from django.utils.deprecation import MiddlewareMixin
    
    class CorsMiddleWare(MiddlewareMixin):
        def process_response(self, request, response):
            # 简单请求,加个响应头就可以了
            response["Access-Control-Allow-Origin"] = "*"       # 允许所有的源(针对的是浏览器的同源策略)
            if request.method == "OPTIONS":
                response["Access-Control-Allow-Headers"] = "Content-Type,a,token"
                # 当是预检请求时,允许携带Content-Type,a,token请求头
                # content-type允许的是请求头中的Contend-Type键值对,
                # 简单请求只允许application/x-www-from-urlencoded、multipart/form-data、text/plain这三种类型的请求,
                # 当前端发送json请求时,如果不设置content-type就不被允许
                # a ,token请求头时我们在前端发送axios自定义的请求头
                response["Access-Control-Allow-Methods"] = "POST, PUT, PATCH, DELETE"  # 除了简单请求外这些请求方式也都允许
            return response
    

      

    # views.py文件
    from course.utils.authentication import MyAuth
    
    class CourseView(ModelViewSet):
        authentication_classes = [MyAuth, ]     # 进行局部认证,所有走这个视图函数的都需要认证,在我们这里是都要携带token请求头
        queryset = Course.objects.all()
        serializer_class = CourseModelSerializer
    
        def list(self, request, *args, **kwargs):
            print(request.META.get('HTTP_A'))
            print(request.META.get('HTTP_TOKEN'))
            queryset = self.filter_queryset(self.get_queryset())
            page = self.paginate_queryset(queryset)
    
            response={"code":1000,"data":None,"err_msg":""}
    
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                response["data"]=serializer.data
                return self.get_paginated_response(response)
    
            serializer = self.get_serializer(queryset, many=True)
            response["data"] = serializer.data
            return Response(response)
    

      

    #  authentication.py 自己写的认证组件
    from rest_framework import authentication
    from rest_framework.exceptions import AuthenticationFailed
    from course.models import Userinfo, UserToken
    
    class MyAuth(authentication.BaseAuthentication):
        def authenticate(self, request):
            if request.method == "OPTIONS":  # 复杂请求走预检时,直接返回,走CorsMiddleWare中间件中的process_response,给响应加允许的头
                return
            token = request.META.get('HTTP_TOKEN')	# 不是复杂请求时,从request.META拿到请求头携带的数据,django会对我们的请求头做处理,前端axios发送的请求头是token,django拿到的请求头就会变成HTTP_TOKEN,而且这里的request也是restframework重新封装后的request
            user_obj = UserToken.objects.filter(token=token).first() # 获取前端传过来的token
            if not user_obj:
                raise AuthenticationFailed("无效的token")
            return user_obj.user, token
    

      

    # 前端axios请求文件
     category_click_all: function () {
                    this.current = -1;
                    let that = this;
                    // console.log(this.$store.state.token,'token已经从仓库中拿到了)
                    this.$axios.request({
                        url: "http://127.0.0.1:8000/course/",     //请求地址
                        method: "get",
                        headers: {
                            a: '1',
                            token: this.$store.state.token,       //携带的请求头
                        },
                    }).then(function (res) {
                        console.log("res:", res);
                        that.course_list = res.data.data
                    }).catch(function (data) {
                        console.log(data)
                    })
    
                },
    

      

    #浏览器跨域:
    1,先走预检请求 request.method == "OPTIONS",这和get post是同级别的请求
    2,vue发axios携带请求头时,get请求,这是第二次请求
      当没有认证组件时,第一次请求在视图函数中没有找到相应的函数来处理options请求,最后走中间件,在response响应头中添加了允许的请求头和所有的源,表示允许携带请求头
      第二次请求是get请求,视图函数可以进行处理,可以在request.META中拿到请求头,当然最后走中间件process_response
      
      当有认证组件时,第一次请求到来先走认证组件,在认证组件中进行判断,如果是options请求return,这是执行中间件的process_response方法,响应预检请求
      第二次请求get请求,这是就可以拿到request.META中的请求头数据了
    

      

     

  • 相关阅读:
    Install the Maven in your computer
    《李嘉诚全传》--孙良珠
    Crystal Reports 2008(水晶报表) 第一个报表
    《唤醒心中的巨人》--[美]安东尼·罗宾
    《写给女人》--[美]桃乐丝·卡耐基
    Crystal Reports 2008(水晶报表) JDBC连接mysql数据库
    Crystal Reports 2008(水晶报表) 启动时检查更新
    Crystal Reports 2008(水晶报表) 安装
    《百年孤独》--[哥伦比亚]加夫列尔·加西亚·马尔克斯
    《自己拯救自己》--[英]塞缪尔·斯迈尔斯
  • 原文地址:https://www.cnblogs.com/perfey/p/9963445.html
Copyright © 2011-2022 走看看