zoukankan      html  css  js  c++  java
  • Django-CBV和跨域请求伪造

    1. django模式

    def users(request):
        user_list = ['alex','oldboy']
        return HttpResponse(json.dumps((user_list)))
    FBV,function base view
    路由:
        url(r'^students/', views.StudentsView.as_view()),
    视图: 通过发射来找到对应的方法去执行
        from django.views import View
        class StudentsView(View):
        def get(self,request,*args,**kwargs):
            return HttpResponse('GET')
    
            def post(self, request, *args, **kwargs):
            return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
            return HttpResponse('PUT')
    
            def delete(self, request, *args, **kwargs):
            return HttpResponse('DELETE')        
    CBV,class base view

    详谈cbv工作模式

    基于反射实现根据请求的方式不同,执行不同的方法

    原理

    -- url -> view方法 -> dispatch方法(反射执行其他:GET/POST/DELETE/PUT)

    流程

    class StudentsView(View):
        def dispatch(self, request, *args, **kwargs):
        print('before')
        ret=super(StudentsView,self).dispatch(request,*args,**kwargs)
        print('after')
        return ret
    
        def get(self,request,*args,**kwargs):
        return HttpResponse('GET')
    
        def post(self, request, *args, **kwargs):
        return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
        return HttpResponse('PUT')
    
        def delete(self, request, *args, **kwargs):
        return HttpResponse('DELETE')
    cbv执行父类的dispatch方法

    2. 面向对象的继承

    多个类共用的功能,为了避免重复编写

    from django.views import View
    最左原则
    class MyBaseView(object):
        def dispatch(self, request, *args, **kwargs):
            print('before')
            ret = super(MyBaseView, self).dispatch(request, *args, **kwargs)
            print('after')
            return ret
    
    
    class StudentsView(MyBaseView, View):
        def get(self, request, *args, **kwargs):
            print('get方法')
            return HttpResponse('GET')
    
        def post(self, request, *args, **kwargs):
            return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
            return HttpResponse('PUT')
    
        def delete(self, request, *args, **kwargs):
            return HttpResponse('DELETE')
        
    
    class TeachersView(MyBaseView, View):
        def get(self, request, *args, **kwargs):
            return HttpResponse('GET')
    
        def post(self, request, *args, **kwargs):
            return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
            return HttpResponse('PUT')
    
        def delete(self, request, *args, **kwargs):
            return HttpResponse('DELETE')
    继承父类的dispatch方法

    3. 面向对象的封装

    class File:
        文件增删改查方法
                        
    Class DB:
        数据库的方法
    同一类方法封装到类中
    class File:
        def __init__(self,a1,a2):
            self.a1 = a1 
        self.xxx = a2
        def get:...
        def delete:...
        def update:...
        def add:...
                        
    obj1 = File(123,666)   将数据123,666 封装到对象中
    obj2 = File(456,999)
    数据封装到对象中
    from django.test import TestCase
    
    # Create your tests here.
    
    ## 封装示例
    
    class Request(object):
        def __init__(self,obj):   # OBJ=对象B,AUTH的这个对象
            self.obj = obj
    
        @property        # 静态方法
        def user(self):           # REQ.USER执行这里,返回 self.obj.authticate() = self.B.authticat() = Auth.authticat() = 'JOKER'
            return self.obj.authticate()
    
    class Auth(object):
        def __init__(self,name,age):  # NAME=JOKER,AGE=18
            self.name = name
            self.age = age
    
        def authticate(self):
            return self.name  # 返回类的属性NAME
    
    
    class APIView(object):
        def dispatch(self):   # 方法被执行
            self.f2()         # SELF就是这个类,调用F2()
    
        def f2(self):         # 调用属性方法
            b = Auth('joker',18)   # 实例化Auth,得到对象B
            req = Request(b)       # 实例化Request,得到对象REQ
            print(req.user)        #
    
    obj = APIView()     # 得到APIView实例化对象OBJ
    obj.dispatch()      # 调用属性方法
    封装示例

    4. django中间件

    - process_request
    - process_view
    - process_response
    - process_exception
    - process_render_template
    五种方法

    中间件做过什么?

    -权限  -登陆验证

    4.1 django的csrf是如何实现?

    1 a. 请求来,第一次来GET,不仅给你数据还给你一个大字符串,但是只能我自己反解,那你提交数据的时候要带着这个字符串
    2    取消 MIDDLEWARE里面的注释,发送login登录时候,会有CSRFTOKEN的COOKIES
    3 b. 无CSRF时存在隐患
    4    所有网页都可以向你的网页提交数据
    5 c. Form提交(CSRF)
    6    {% csrf_token %}
    7 d. Ajax提交(CSRF)
    8    拿到请求头里面去,发送过去就可以了,CSRF请求头 X-CSRFToken

    发生在,process_view方法,因为要检查函数是否被装饰器装饰
    - 检查视图是否被 @csrf_exempt (免除csrf认证)
    - 去请求体或cookie中获取token

    请求时候会随机产生字符串,在访问的时候会携带这个随机字符串

    4.2 针对django,fbv模式如何关闭验证

    from django.views.decorators.csrf import csrf_exempt(无需验证),csrf_protect(需验证)

    找到需要验证的函数,@csrf_exempt,@csrf_protect

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',  # 全站使用csrf认证
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    from django.views.decorators.csrf import csrf_exempt
    
    
    @csrf_exempt  # 该函数无需认证
    def users(request):
        user_list = ['alex', 'oldboy']
        return HttpResponse(json.dumps((user_list)))
    情况一,全局验证,该函数无需验证
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware', # 全站不使用csrf认证
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    from django.views.decorators.csrf import csrf_protect
    
    
    @csrf_protect  # 该函数需认证
    def users(request):
        user_list = ['alex', 'oldboy']
        return HttpResponse(json.dumps((user_list)))
    情况二,全局不验证,该函数需验证

    4.3 针对django, cbv模式如何关闭验证

    dispatch函数,或者方法,是通过反射来执行相对应的方法,控制它的验证或不验证

    from django.views.decorators.csrf import csrf_exempt(无需验证),csrf_protect(需验证)
    from django.utils.decorators import method_decorator

    - @method_decorator(csrf_exempt)
    - 在dispatch方法中(单独方法无效)

    可以针对验证的函数去写,但是不能单独写,要写在@method_decorator里面

    @method_decorator(csrf_exempt),@method_decorator(csrf_protect)

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator
    
    
    class StudentsView(View):
        @method_decorator(csrf_exempt)  # 无需验证
        def dispatch(self, request, *args, **kwargs):
            return super(StudentsView, self).dispatch(request, *args, **kwargs)
    
        def get(self, request, *args, **kwargs):
            print('get方法')
            return HttpResponse('GET')
    
        def post(self, request, *args, **kwargs):
            return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
            return HttpResponse('PUT')
    
        def delete(self, request, *args, **kwargs):
            return HttpResponse('DELETE')
    针对dispatch函数

    可以针对类,然后指定类里面的方法去验证还是不验证,同样需要写在@method_decorator里面

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator
    
    
    @method_decorator(csrf_exempt, name='dispatch')  # 无需验证
    class StudentsView(View):
    
    
    def get(self, request, *args, **kwargs):
        print('get方法')
        return HttpResponse('GET')
    
        def post(self, request, *args, **kwargs):
            return HttpResponse('POST')
    
        def put(self, request, *args, **kwargs):
            return HttpResponse('PUT')
    
        def delete(self, request, *args, **kwargs):
            return HttpResponse('DELETE')
    针对dispatch方法

    5. 总结 

    - cbv
    - 本质,基于反射来实现
    - 流程:路由,view,dispatch(反射)
    - 取消csrf认证(装饰器要加到dispatch方法上且method_decorator装饰)

    - csrf
    - 基于中间件的process_view方法
    - 装饰器给单独函数进行设置(认证或无需认证)

    -urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^students/', views.StudentsView.as_view()), 点 as_view查看源码

    ]

    class View(object):
        """
        Intentionally simple parent class for all views. Only implements
        dispatch-by-method and simple sanity checking.
        """
    
        http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    
        def __init__(self, **kwargs):
            """
            Constructor. Called in the URLconf; can contain helpful extra
            keyword arguments, and other things.
            """
            # Go through keyword arguments, and either save their values to our
            # instance, or raise an error.
            for key, value in six.iteritems(kwargs):
                setattr(self, key, value)
    
        @classonlymethod
        def as_view(cls, **initkwargs):
            """
            Main entry point for a request-response process.
            """
            for key in initkwargs:
                if key in cls.http_method_names:
                    raise TypeError("You tried to pass in the %s method name as a "
                                    "keyword argument to %s(). Don't do that."
                                    % (key, cls.__name__))
                if not hasattr(cls, key):
                    raise TypeError("%s() received an invalid keyword %r. as_view "
                                    "only accepts arguments that are already "
                                    "attributes of the class." % (cls.__name__, key))
    
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
                self.request = request
                self.args = args
                self.kwargs = kwargs
                return self.dispatch(request, *args, **kwargs)
            view.view_class = cls
            view.view_initkwargs = initkwargs
    
            # take name and docstring from class
            update_wrapper(view, cls, updated=())
    
            # and possible attributes set by decorators
            # like csrf_exempt from dispatch
            update_wrapper(view, cls.dispatch, assigned=())
            return view
    
        def dispatch(self, request, *args, **kwargs):
            # Try to dispatch to the right method; if a method doesn't exist,
            # defer to the error handler. Also defer to the error handler if the
            # request method isn't on the approved list.
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
    cbv反射源码

    django请求周期

    FBV          wsgi--中间件--路由--视图--模版--渲染--返回

    CBV          wsgi--中间件--路由--dispatch

    RESTFRAMEWORK    wsgi--中间件--路由--dispatch

  • 相关阅读:
    【Django】django 处理request流程细节(转)
    【Django】request 处理流程(转)
    【Django】中间件
    【HTML】DocType
    【CSS】伪类与伪元素
    【nodejs】nodejs 的linux安装(转)
    【chrome】 chrome 开发者工具
    【samba】samba 用户权限配置(转)
    form表单组件
    自定义分页器
  • 原文地址:https://www.cnblogs.com/jokerbj/p/8507034.html
Copyright © 2011-2022 走看看