1.中间件加载过程源码分析
1.请求到达:请求首先通过 Django 的 Handler 处理器,具体是在 django.core.handlers.base.BaseHandler 类中的 get_response 方法开始处理。
2.中间件处理链创建: 在 get_response 方法中,Django 通过self.load_middleware()函数构建了一个中间件处理链。load_middleware 方法会遍历项目的中间件设置(在 settings.py 中配置),并按顺序加载中间件。
3.中间件处理链执行: 在 get_response 方法中,当请求到达时,Django 会遍历中间件处理链,依次调用每个中间件的 process_request 方法。
4.视图处理: 请求经过中间件的 process_request 处理后,进入视图处理阶段。视图是在 django.core.handlers.base.BaseHandler 类的 get_response 方法中调用的。
5.中间件处理链执行(响应阶段): 在视图函数执行后,Django 再次遍历中间件处理链,调用每个中间件的 process_response 方法。
# django/core/handlers/base.py
class BaseHandler:
def __init__(self):
self._request_middleware = self.load_middleware('request')
self._response_middleware = self.load_middleware('response')
def load_middleware(self, phase):
middleware_list = []
# 获取 settings.py 中配置的中间件路径列表
middleware_paths = settings.MIDDLEWARE
for middleware_path in middleware_paths:
middleware = import_string(middleware_path)
if hasattr(middleware, f'process_{phase}'):
middleware_list.append(middleware)
return middleware_list
def get_response(self, request):
# 请求到达时执行请求阶段中间件
for middleware in self._request_middleware:
response = middleware.process_request(request)
# ...
# 视图处理
response = wrapped_callback(request, *callback_args, **callback_kwargs)
# 视图处理后执行响应阶段中间件
for middleware in self._response_middleware:
response = middleware.process_response(request, response)
# ...
return response
2.crsf_token生成和校验源码详解
在 Django 中,CSRF(Cross-Site Request Forgery)防护是通过生成和验证 CSRF 令牌(CSRF Token)来实现的。
-
CSRF 令牌生成:
CSRF 令牌生成是在 Django 的 django.middleware.csrf.CsrfViewMiddleware 中间件中完成的。具体的源码位于 django.middleware.csrf 模块中的CsrfViewMiddleware
类。class CsrfViewMiddleware(MiddlewareMixin): def process_view(self, request, callback, callback_args, callback_kwargs): # ... # 生成 CSRF 令牌 csrf_token = self._get_token(request) # 将生成的令牌添加到请求的上下文中 request.csrf_token = csrf_token def _get_token(self, request): # 生成 CSRF 令牌 return get_token(request) def get_token(request): if "CSRF_COOKIE" not in request.META: # 如果没有 CSRF Cookie,生成一个新的 CSRF 令牌 request.META["CSRF_COOKIE"] = _get_new_csrf_key() return request.META["CSRF_COOKIE"] # 使用了一定的随机性,结合时间戳、随机数、和字符串生成了一个新的 CSRF 令牌。 def _get_new_csrf_key(): return _salt() + md5(("%s%s" % (randrange(0, _MAX_CSRF_KEY), get_random_string())).encode()).hexdigest()
-
CSRF 令牌校验:
CSRF 令牌的校验是在 Django 的 django.middleware.csrf.CsrfViewMiddleware 中间件中的 process_view 方法中完成的。class CsrfViewMiddleware(MiddlewareMixin): def process_view(self, request, callback, callback_args, callback_kwargs): # ... # 校验 CSRF 令牌 self._enforce_csrf(request, response) def _enforce_csrf(self, request, response): # 校验 CSRF 令牌 csrf_token = request.POST.get('csrfmiddlewaretoken') or request.GET.get('csrfmiddlewaretoken') if csrf_token != request.csrf_token: # CSRF 令牌校验失败,触发异常 raise CsrfViewMiddleware._get_failure_view()(request, reason='CSRF token missing or incorrect.')