1.csrf原理

csrf要求发送post,put或delete请求的时候,是先以get方式发送请求,服务端响应时会分配一个随机字符串给客户端,客户端第二次发送post,put或delete请求时携带上次分配的随机字符串到服务端进行校验

2.Django中的CSRF中间件

首先,我们知道Django中间件作用于整个项目。

在一个项目中,如果想对全局所有视图函数或视图类起作用时,就可以在中间件中实现,比如想实现用户登录判断,基于用户的权限管理(RBAC)等都可以在Django中间件中来进行操作

Django内置了很多中间件,其中之一就是CSRF中间件

MIDDLEWARE_CLASSES = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.auth.middleware.SessionAuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]

上面第四个就是Django内置的CSRF中间件

3.Django中间件的执行流程

Django中间件中最多可以定义5个方法

process_request
process_response
process_view
process_exception
process_template_response

Django中间件的执行顺序

1.请求进入到Django后,会按中间件的注册顺序执行每个中间件中的process_request方法 如果所有的中间件的process_request方法都没有定义return语句,则进入路由映射,进行url匹配 否则直接执行return语句,返回响应给客户端

2.依次按顺序执行中间件中的process_view方法 如果某个中间件的process_view方法没有return语句,则根据第1步中匹配到的URL执行对应的视图函数或视图类 如果某个中间件的process_view方法中定义了return语句,则后面的视图函数或视图类不会执行,程序会直接返回

3.视图函数或视图类执行完成之后,会按照中间件的注册顺序逆序执行中间件中的process_response方法 如果中间件中定义了return语句,程序会正常执行,把视图函数或视图类的执行结果返回给客户端 否则程序会抛出异常

4.程序在视图函数或视图类的正常执行过程中 如果出现异常,则会执行按顺序执行中间件中的process_exception方法 否则process_exception方法不会执行 如果某个中间件的process_exception方法中定义了return语句,则后面的中间件中的process_exception方法不会继续执行了

5.如果视图函数或视图类中使用render方法来向客户端返回数据,则会触发中间件中的process_template_response方法

4.Django CSRF中间件的源码解析

Django CSRF中间件的源码

class CsrfViewMiddleware(MiddlewareMixin):def _accept(self, request):request.csrf_processing_done = Truereturn Nonedef _reject(self, request, reason):logger.warning('Forbidden (%s): %s', reason, request.path,extra={'status_code': 403,'request': request,})return _get_failure_view()(request, reason=reason)def _get_token(self, request):if settings.CSRF_USE_SESSIONS:try:return request.session.get(CSRF_SESSION_KEY)except AttributeError:raise ImproperlyConfigured('CSRF_USE_SESSIONS is enabled, but request.session is not ''set. SessionMiddleware must appear before CsrfViewMiddleware ''in MIDDLEWARE%s.' % ('_CLASSES' if settings.MIDDLEWARE is None else ''))else:try:cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]except KeyError:return Nonecsrf_token = _sanitize_token(cookie_token)if csrf_token != cookie_token:# Cookie token needed to be replaced;# the cookie needs to be reset.request.csrf_cookie_needs_reset = Truereturn csrf_tokendef _set_token(self, request, response):if settings.CSRF_USE_SESSIONS:request.session[CSRF_SESSION_KEY] = request.META['CSRF_COOKIE']else:response.set_cookie(settings.CSRF_COOKIE_NAME,request.META['CSRF_COOKIE'],max_age=settings.CSRF_COOKIE_AGE,domain=settings.CSRF_COOKIE_DOMAIN,path=settings.CSRF_COOKIE_PATH,secure=settings.CSRF_COOKIE_SECURE,httponly=settings.CSRF_COOKIE_HTTPONLY,)patch_vary_headers(response, ('Cookie',))def process_request(self, request):csrf_token = self._get_token(request)if csrf_token is not None:# Use same token next time.request.META['CSRF_COOKIE'] = csrf_tokendef process_view(self, request, callback, callback_args, callback_kwargs):if getattr(request, 'csrf_processing_done', False):return Noneif getattr(callback, 'csrf_exempt', False):return Noneif request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):if getattr(request, '_dont_enforce_csrf_checks', False):return self._accept(request)if request.is_secure():referer = force_text(request.META.get('HTTP_REFERER'),strings_only=True,errors='replace')if referer is None:return self._reject(request, REASON_NO_REFERER)referer = urlparse(referer)if '' in (referer.scheme, referer.netloc):return self._reject(request, REASON_MALFORMED_REFERER)if referer.scheme != 'https':return self._reject(request, REASON_INSECURE_REFERER)good_referer = (settings.SESSION_COOKIE_DOMAINif settings.CSRF_USE_SESSIONSelse settings.CSRF_COOKIE_DOMAIN)if good_referer is not None:server_port = request.get_port()if server_port not in ('443', '80'):good_referer = '%s:%s' % (good_referer, server_port)else:good_referer = request.get_host()good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)good_hosts.append(good_referer)if not any(is_same_domain(referer.netloc, host) for host in good_hosts):reason = REASON_BAD_REFERER % referer.geturl()return self._reject(request, reason)csrf_token = request.META.get('CSRF_COOKIE')if csrf_token is None:return self._reject(request, REASON_NO_CSRF_COOKIE)request_csrf_token = ""if request.method == "POST":try:request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')except IOError:passif request_csrf_token == "":request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')request_csrf_token = _sanitize_token(request_csrf_token)if not _compare_salted_tokens(request_csrf_token, csrf_token):return self._reject(request, REASON_BAD_TOKEN)return self._accept(request)def process_response(self, request, response):if not getattr(request, 'csrf_cookie_needs_reset', False):if getattr(response, 'csrf_cookie_set', False):return responseif not request.META.get("CSRF_COOKIE_USED", False):return responseself._set_token(request, response)response.csrf_cookie_set = Truereturn response

从上面的源码中可以看到,CsrfViewMiddleware中间件中定义了process_request,process_view和process_response三个方法

先来看process_request方法

def _get_token(self, request):  if settings.CSRF_USE_SESSIONS:  try:  return request.session.get(CSRF_SESSION_KEY)  except AttributeError:  raise ImproperlyConfigured(  'CSRF_USE_SESSIONS is enabled, but request.session is not '  'set. SessionMiddleware must appear before CsrfViewMiddleware ' 'in MIDDLEWARE%s.' % ('_CLASSES' if settings.MIDDLEWARE is None else '')  )  else:  try:  cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]  except KeyError:  return None  csrf_token = _sanitize_token(cookie_token)  if csrf_token != cookie_token:  # Cookie token needed to be replaced;  # the cookie needs to be reset.  request.csrf_cookie_needs_reset = True  return csrf_tokendef process_request(self, request):  csrf_token = self._get_token(request)  if csrf_token is not None:  # Use same token next time.  request.META['CSRF_COOKIE'] = csrf_token

从Django项目配置文件夹中读取CSRF_USE_SESSIONS的值,如果获取成功,则从session中读取CSRF_SESSION_KEY的值,默认为'_csrftoken',如果没有获取到CSRF_USE_SESSIONS的值,则从发送过来的请求中获取CSRF_COOKIE_NAME的值,如果没有定义则返回None。

再来看process_view方法

在process_view方法中,先检查视图函数是否被csrf_exempt装饰器装饰,如果视图函数没有被csrf_exempt装饰器装饰,则程序继续执行,否则返回None。接着从request请求头中或者cookie中获取携带的token并进行验证,验证通过才会继续执行与URL匹配的视图函数,否则就返回403 Forbidden错误。

实际项目中,会在发送POST,PUT,DELETE,PATCH请求时,在提交的form表单中添加

{% csrf_token %}

即可,否则会出现403的错误

5.csrf_exempt装饰器和csrf_protect装饰器

5.1 基于Django FBV

在一个项目中,如果注册起用了CsrfViewMiddleware中间件,则项目中所有的视图函数和视图类在执行过程中都要进行CSRF验证。

此时想使某个视图函数或视图类不进行CSRF验证,则可以使用csrf_exempt装饰器装饰不想进行CSRF验证的视图函数

from django.views.decorators.csrf import csrf_exempt@csrf_exempt
def index(request):  pass

也可以把csrf_exempt装饰器直接加在URL路由映射中,使某个视图函数不经过CSRF验证

from django.views.decorators.csrf import csrf_exempt  from users import views  urlpatterns = [  url(r'^admin/', admin.site.urls),  url(r'^index/',csrf_exempt(views.index)),
]

同样的,如果在一个Django项目中,没有注册起用CsrfViewMiddleware中间件,但是想让某个视图函数进行CSRF验证,则可以使用csrf_protect装饰器

csrf_protect装饰器的用法跟csrf_exempt装饰器用法相同,都可以加上视图函数上方装饰视图函数或者在URL路由映射中直接装饰视图函数

from django.views.decorators.csrf import csrf_exempt  @csrf_protect
def index(request):  pass

或者

from django.views.decorators.csrf import csrf_protect  from users import views  urlpatterns = [  url(r'^admin/', admin.site.urls),  url(r'^index/',csrf_protect(views.index)),
]

5.1 基于Django CBV

上面的情况是基于Django FBV的,如果是基于Django CBV,则不可以直接加在视图类的视图函数中了

此时有三种方式来对Django CBV进行CSRF验证或者不进行CSRF验证

方法一,在视图类中定义dispatch方法,为dispatch方法加csrf_exempt装饰器

from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decoratorclass UserAuthView(View):@method_decorator(csrf_exempt)def dispatch(self, request, *args, **kwargs):return super(UserAuthView,self).dispatch(request,*args,**kwargs)def get(self,request,*args,**kwargs):passdef post(self,request,*args,**kwargs):passdef put(self,request,*args,**kwargs):passdef delete(self,request,*args,**kwargs):pass

方法二:为视图类上方添加装饰器

@method_decorator(csrf_exempt,name='dispatch')
class UserAuthView(View):def get(self,request,*args,**kwargs):passdef post(self,request,*args,**kwargs):passdef put(self,request,*args,**kwargs):passdef delete(self,request,*args,**kwargs):pass

方式三:在url.py中为类添加装饰器

from django.views.decorators.csrf import csrf_exempturlpatterns = [url(r'^admin/', admin.site.urls),url(r'^auth/', csrf_exempt(views.UserAuthView.as_view())),
]

csrf_protect装饰器的用法跟上面一样

详解Django的CSRF认证相关推荐

  1. python django restful_详解Django rest_framework实现RESTful API

    一.什么是REST 面向资源是REST最明显的特征,资源是一种看待服务器的方式,将服务器看作是由很多离散的资源组成.每个资源是服务器上一个可命名的抽象概念.因为资源是一个抽象的概念,所以它不仅仅能代表 ...

  2. 详解Cisco ACS AAA认证

    详解Cisco ACS AAA认证 近来,有些同学会问到关于AAA认证的问题,以及cisco ACS如何使用,那么今天我们就主要来讲一下关于这方面的知识. AAA代表Authentication.Au ...

  3. 详解Django的Models(django基础四)

    文章目录 model基础 model设计时的总结 orm概述 什么是ORM orm的功能 Models介绍 model创建语法 model案例演示 models的属性与字段(field) 1.fiel ...

  4. 【PHP基础-9】Session机制详解及Session身份认证应用案例

    目录 1 Session 机制概述 1.1 什么是Session 1.2 Session作用 1.3 session的运行机制: 2 Session应用案例 2.1 实验要求 2.2 实验环境 2.3 ...

  5. python3 urllib代理_Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)

    我们可以利用urllib来抓取远程的数据进行保存哦,以下是python3 抓取网页资源的多种方法,有需要的可以参考借鉴. 1.最简单 import urllib.request response = ...

  6. (转载)详解Hive配置Kerberos认证

    Hive提供了运行SQL语句查询存储在HDFS上数据的能力,Hive提供的查询引擎,可以将SQL语句转化成MapReduce任务,提交到Hadoop集群上执行.MapReduce任务运行的结果会存在H ...

  7. 详解Django中Request对象的相关用法

    1.从Request对象中获取数据 我们在第三章讲述View的函数时已经介绍过HttpRequest对象了,但当时并没有讲太多. 让我们回忆下:每个view函数的第一个参数是一个HttpRequest ...

  8. 详解django三种文件下载方式

    推荐使用FileResponse,从源码中可以看出FileResponse是StreamingHttpResponse的子类,内部使用迭代器进行数据流传输. 在实际的项目中很多时候需要用到下载功能,如 ...

  9. Linux中pam认证详解,linux中pam认证解析

    pam认证机制:简单来说就是linux系统采取的这一种对不同用户以及系统中的不同服务进行的安全认证机制. 认证流程:linux系统首先确定所需认证的服务,然后加载相应的PAM的配置文件(位于/etc/ ...

  10. 详解Wi-Fi连接上网认证接入的原理和过程

    引言 在正式看文章之前,我们需要了解的知识是:WiFi的STA和AP模式指什么? 1.AP,也就是无线接入点,是一个无线网络的创建者,是网络的中心节点.一般家庭或办公室使用的无线路由器就一个AP. 2 ...

最新文章

  1. java反射(reflect)机制模拟javabean的实现
  2. 中setting怎么配置_用VSCode配置Latex
  3. 快速学习正则表达式,不用死记硬背,这里有份中文资源和互动学习网站
  4. 【计算摄影】计算机如何学会自动裁剪图片(自动构图)?
  5. FB 宕机,Telegram 用户疯涨,P**hub 流量猛增
  6. Cookie中不能有空格_PHP 使用cookie
  7. python决策树 value_机器学习 | 算法笔记(四)- 决策树算法以及代码实现
  8. OpenJudge NOI 1.8 22:神奇的幻方
  9. 简谈java的split
  10. ubuntu 强制结束 pycharm
  11. 递归与分治策略之利用中位数线性时间选择
  12. 2022年数学建模国赛(A题/B题/C题)评阅要点
  13. 初步认识马尔可夫链与马尔可夫链的简单应用
  14. Win10 + vs2017 编译并配置tesseract-5.0.0-alpha 遇到的问题
  15. 均值、均方值、方差、均方差和协方差概念及其物理意义
  16. Kaggle案例泰坦尼克号问题
  17. 2021-09-20德天老师更新好学易懂的python办公自动化批量生成docx
  18. 微信访问时,提示:该地址为ip地址,请使用域名访问网站
  19. 问题—抱怨?人品差?别搞笑了!
  20. PHP连接MSSQL配置和PHP代码演示

热门文章

  1. (附源码)计算机毕业设计ssm高校第二课堂管理系统
  2. 让 M1 芯片的 MacBook Pro 同时支持两个 4k 显示器
  3. android e.printStackTrace()异常处理
  4. HTML和CSS的知识点
  5. 我们终究是一群平凡的人
  6. 快手用计算机弹奏,【图片】【CJ他家】弹计算器视频传送门、计算器谱等随时更新!_计算器音乐吧_百度贴吧...
  7. python数据可视化学习之随机漫步
  8. 光纤熔接机市场现状及未来发展趋势
  9. 电脑账户服务器未能登录拒绝访问,win7系统开机提示服务未能登入拒绝访问的解决方法...
  10. Oracle 11g安装过程中提示先决条件检查不通过的解决方法