Django-CBV和跨域请求伪造
1. django模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def users(request): user_list = ['alex','oldboy'] return HttpResponse(json.dumps((user_list)))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
路由: 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工作模式
基于反射实现根据请求的方式不同,执行不同的方法
原理
-- url -> view方法 -> dispatch方法(反射执行其他:GET/POST/DELETE/PUT)
流程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')
2. 面向对象的继承
多个类共用的功能,为了避免重复编写
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')
3. 面向对象的封装
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class File: 文件增删改查方法 Class DB: 数据库的方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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中间件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
- 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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')
可以针对类,然后指定类里面的方法去验证还是不验证,同样需要写在@method_decorator里面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')
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查看源码
]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
django请求周期
FBV wsgi--中间件--路由--视图--模版--渲染--返回
CBV wsgi--中间件--路由--dispatch
RESTFRAMEWORK wsgi--中间件--路由--dispatch