本文环境python3.5.2,django1.10.x系列
介绍django中关于跨域请求保护的内容,主要由其中一个中间件完成,下面稍微讲一下关于csrf原理和django中间件在请求中的作用,重点将放到CsrfViewMiddleware中间键的源码讲解。
csrf原理
CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。 如下:其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
django中间件作用
Django文档中对中间件的解释
中间件是Django请求/响应处理的链接框架。它是一个轻巧的底层的“插件”系统,用于全局改变Django的输入或输出。
每个中间件组件负责执行某些特定功能。例如,Django包含一个中间件组件AuthenticationMiddleware,它将用户与使用会话的请求相关联。
在请求阶段,调用views之前,django按照MIDDLEWARE_CLASSES中定义的顺序从上到下调用中间件。有两个hooks:
process_request()
process_view()
在响应阶段,调用views之后,中间件被从下到上反向调用,有三个hooks:
process_exception() (只有当view中raise一个例外时)
process_template_response() (只有view中返回template时)
process_response()
源码分析
下面详细解释一下中间件CsrfViewMiddleware的源代码,代码旁边都有注释。
class CsrfViewMiddleware(MiddlewareMixin):
"""
Middleware that requires a present and correct csrfmiddlewaretoken
for POST requests that have a CSRF cookie, and sets an outgoing
CSRF cookie.
This middleware should be used in conjunction with the csrf_token template
tag.
"""
# The _accept and _reject methods currently only exist for the sake of the
# requires_csrf_token decorator.
def _accept(self, request):
# Avoid checking the request twice by adding a custom attribute to
# request. This will be relevant when both decorator and middleware
# are used.
request.csrf_processing_done = True # 避免检查middleware或者装饰器检查多次request
return None
def _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 process_view(self, request, callback, callback_args, callback_kwargs):
if getattr(request, 'csrf_processing_done', False): # 检查csrf验证参数,如果已经验证,则返回None
return None
try:
cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME] # CSRF_SESSION_KEY= "csrftoken"
except KeyError:
csrf_token = None
else: