csrf装饰器
12.11.1 基本内容
- csrf装饰器只可以加到
dispatch上 - csrf_exempt(豁免) 某个视图不需要进行csrf校验,可以直接进行访问
- csrf_protect 某个视图需要进行csrf校验 即使中间件注释也要校验
@method_decorator(csrf_exempt)只能加到dispatch上@method_decorator(csrf_protect )加到任意函数或类都可以,代表必须要csrf校验- 只使用这个,没有打开中间件,需要使用下面的
ensure_csrf_cookie来获取到cookie,因为中间件有个功能是设置cookie中的csrftoken
- 只使用这个,没有打开中间件,需要使用下面的
from django.views.decorators.csrf import csrg_exempt,csrf_protect,ensure_csrf_cookie
from django.utils.decorators import method_decorator
#ensure_csrf_cookie 确保生成cookie
# 一种是打开中间件,模板中使用 csrf token
# 上述两种方式都可以
@method_decorator(csrf_exempt)
def dispatch(self,request,*args,**kwargs):
return ret
12.11.2 csrf功能
-
csrf中间件执行process_request:- 从cookie中获取csrftoken的值
- csrftoken的值放入到
request.META
-
执行
process_view- 查看视图函数是否使用csrf_exempt装饰器,使用了就不进行校验了
- 如果是GET HEAD OPTIONS TRACE 不进行csrf校验
- 其他的比如 post put 是需要进行校验的
- 进行csrf校验:
- 获取cookie中csrftoken的值和POST请求中csrfmiddlewaretoken的值,成功就接受请求,不成功就拒绝请求。
- 如果获取不到csrfmiddlewaretoken的值,通过request.META获取X-csrftoken的值,得到request_csrf_token的值,后再和cookie中的csrftoken的值比较。
-
middleware源码解析
- 'django.middleware.csrf.CsrfViewMiddleware',
CsrfViewMiddleware是个类, 在其中封装 并首先执行process_request,之中再执行_get_token方法,在这个方法中通过request.COOKIE['csrftoken']获取到具体的cookie中的csrftoken的值,之后判断下长度是否是64,然后通过request.META['CSRF_COOKIE'] = csrf_token放入到请求头中- 执行完上个流程后,还会执行
process_view方法,来判断是否继续执行和校验,其中
if getattr(request,'csrf_processing-done',False): return None #代表如果执行了就不执行了 if getattr(callback,'csrf_exempt', False): return None #其中csrf装饰器@method_decorator(csrf_exempt) 中的crsf_exempt中有属性 wrapped_view.csrf_exempt = True 所以函数一旦有这个装饰器,也会执行结束,这也是csrf规避中间件校验的本质 if request.method not in ('GET','HEAD','OPTIONS','TRACE'): #如果除了这四种,都要进行校验 csrf_token = request.META.get('CSRF_COOKIE') #刚刚已经将cookie中的csrf_token信息放到请求头,这部是直接拿出来 if csrf_token is None: return self._reject(request,REASON_NO_CSRF-COOKIE) #这步是返回403forbidden页面 if request.method == 'POST': request_csrf_token = request.POST.get('csrfmiddlewaretoken','') #获取标签中hidden属性 if request_csrf_token =='': request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME,'') #结果是获得'HTTP_X_CSRFTOKEN' 真实的是 x-csrftoken if not _cmpare_salted_tokens(request_csrf_token,csrf_token): return self._reject(request,REASON_BAD_TOKEN) #比较 csrf_token (cookie中的csrf_token) request_csrf_token(标签中的token或者设置的x-csrftoken) return self._accept(request) #这部代表如果是上述四个方法,就不执行校验,返回True

浙公网安备 33010602011771号