# 第四章 架构设计 - 请求处理流程 ## 4.1 请求处理全链路 一个完整的 HTTP 请求在 系统中的处理流程如下: ``` 浏览器 | | (1) 发起HTTP请求 (携带 Authorization: Bearer ) v Nginx | | (2) 反向代理,静态资源由Nginx处理,API请求转发到Django v Django WSGI | | (3) 进入中间件链 v CORS中间件 (corsheaders.middleware.CorsMiddleware) | | (4) 处理跨域请求,添加CORS响应头 v check_login装饰器 (middleware/login_middleware.py) | | (5) 验证JWT token有效性 v URL路由匹配 (application/urls.py) | | (6) 根据URL分发到对应视图类 v PermissionRequired混入类 (middleware/permission_middleware.py) | | (7) 验证用户权限节点 v View视图类 (views.py) | | (8) 解析请求参数,调用Service v Service服务函数 (services.py) | | (9) 执行业务逻辑,操作数据库 v R.ok()/R.failed() (utils/R.py) | | (10) 构造统一JSON响应 v JsonResponse | | (11) 返回响应数据 v 浏览器 ``` ## 4.2 中间件处理顺序 根据 `application/settings.py` 的配置,中间件按以下顺序执行: ```python MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 1. CORS跨域处理 'django.middleware.security.SecurityMiddleware', # 2. 安全处理 'django.contrib.sessions.middleware.SessionMiddleware', # 3. Session处理 'django.middleware.common.CommonMiddleware', # 4. 通用处理 # 'django.middleware.csrf.CsrfViewMiddleware', # CSRF已禁用(使用JWT) 'django.contrib.auth.middleware.AuthenticationMiddleware', # 5. 认证处理 'django.contrib.messages.middleware.MessageMiddleware', # 6. 消息处理 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 7. 点击劫持防护 ] ``` **注意**:`check_login` 和 `PermissionRequired` 不是 Django 中间件,而是通过装饰器和混入类实现的,作用于视图层面。 ## 4.3 JWT 认证流程 ### 4.3.1 登录认证 ```python # 1. 用户提交用户名密码 POST /login { "username": "admin", "password": "123456", "captcha": "abc123" } # 2. 验证通过后生成JWT Token from utils.jwt import create_token payload = { 'userId': user.id, 'username': user.username, 'realname': user.realname } token = create_token(payload, timeout=20) # 20分钟过期 # 3. 返回Token给前端 { "code": 0, "data": { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." }, "msg": "登录成功" } ``` ### 4.3.2 请求认证 ```python # 1. 前端在请求头中携带Token headers = { "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } # 2. check_login装饰器验证Token def check_login(func): def wrapper(request, *args, **kwargs): # 忽略不需要认证的URL ignoreURL = ['/login', '/captcha'] if request.path not in ignoreURL: # 从请求头获取Token access_token = request.headers['Authorization'] access_token = access_token.replace('Bearer ', "") # 验证Token result = parse_payload(access_token) if result['code'] != 0: return R.failed(code=401, msg=result['msg']) return func(request, *args, **kwargs) return wrapper ``` ### 4.3.3 Token 黑名单检查 ```python # 1. 验证Token时先检查黑名单 def parse_payload(token): # 检查Token是否在黑名单中 if is_token_blacklisted(token): return {'code': -1, 'msg': 'token已失效,请重新登录'} # 解密验证JWT令牌 verified_payload = jwt.decode(token, JWT_SALT, algorithms=[JWT_ALGORITHM]) return {'code': 0, 'data': verified_payload} # 2. 黑名单检查使用Redis def is_token_blacklisted(token): redis = get_redis_connection("default") fingerprint = hashlib.sha256(token.encode('utf-8')).hexdigest() key = f'token:blacklist:{fingerprint}' return redis.exists(key) > 0 ``` ## 4.4 权限验证流程 ### 4.4.1 权限节点定义 每个操作对应一个权限节点,格式为 `sys::`: ```python # 示例:案例模块的权限节点 permission_required = ("sys:example:page",) # 分页查询 permission_required = ("sys:example:detail",) # 详情查询 permission_required = ("sys:example:add",) # 添加 permission_required = ("sys:example:update",) # 更新 permission_required = ("sys:example:delete",) # 删除 permission_required = ("sys:example:status",) # 状态更新 ``` ### 4.4.2 权限验证逻辑 ```python class PermissionRequired(PermissionRequiredMixin): def has_permission(self): # 获取所需权限节点 permissions = self.get_permission_required() # 获取当前用户ID user_id = get_user_id(self.request) # 超级管理员(ID=1)自动放行 if user_id and user_id != 1: # 获取用户权限列表 permission_list = services.get_user_permissions(user_id) # 检查是否拥有所需权限 for permission in permissions: if permission not in permission_list: return False return True ``` ### 4.4.3 权限获取逻辑 ```python # application/menu/services.py def get_user_permissions(user_id): if user_id == 1: # 超级管理员拥有所有权限 menu_list = Menu.objects.filter(is_delete=False, type=1, status=0).values() return [item['permission'] for item in menu_list] else: # 普通用户从角色关联中获取权限 sql = ''' SELECT m.* FROM django_menu AS m INNER JOIN django_role_menu AS rm ON m.id=rm.menu_id INNER JOIN django_user_role AS ur ON ur.role_id=rm.role_id WHERE ur.user_id=%s AND (m.type=1 OR (m.type=0 AND m.permission!='')) AND m.status=0 AND m.is_delete=0 ''' menu_list = Menu.objects.raw(sql, [user_id]) return [item.permission for item in menu_list] ``` ## 4.5 业务处理流程 以"添加案例"为例,完整的业务处理流程: ``` 1. View层 (ExampleAddView.post) +-- 检查演示模式 (DJANGO_DEMO) +-- 调用 Service: services.add_example(request) 2. Service层 (add_example) +-- 解析请求体: parse_request_body(request) +-- 表单验证: forms.ExampleForm(data) +-- 处理文件: save_file(avatar, "example") +-- 创建记录: Example.objects.create(...) +-- 返回结果: R.ok(msg="创建成功") 3. Model层 (Example) +-- Django ORM 生成 SQL +-- MySQL 执行 INSERT +-- 自动生成 create_time、update_time ``` ## 4.6 响应格式规范 所有 API 接口返回统一的 JSON 格式: ### 成功响应 ```json { "code": 0, "data": { "id": 1, "name": "案例名称", "status": 1 }, "msg": "操作成功", "ok": true } ``` ### 分页响应 ```json { "code": 0, "data": { "records": [ {"id": 1, "name": "案例1"}, {"id": 2, "name": "案例2"} ], "total": 100, "size": 10, "current": 1, "pages": 10 }, "msg": "操作成功", "ok": true } ``` ### 失败响应 ```json { "code": 1, "data": null, "msg": "操作失败", "ok": false } ``` ### 认证失败响应 ```json { "code": 401, "data": null, "msg": "token已失效,请重新登录", "ok": false } ``` ## 4.7 异常处理机制 ### 4.7.1 全局异常处理 ```python # Service层统一使用 try-except 捕获异常 def add_example(request): try: # 业务逻辑 Example.objects.create(...) return R.ok(msg="创建成功") except Exception as e: logging.error(f"添加案例异常: {str(e)}") return R.failed(msg="添加失败,请稍后重试") ``` ### 4.7.2 表单验证异常 ```python # 表单验证失败时返回具体错误信息 form = ExampleForm(data) if not form.is_valid(): return R.failed(msg=regular.get_err(form)) ``` ### 4.7.3 数据库异常 ```python # 数据库操作异常被捕获并返回友好提示 try: instance.save() except IntegrityError as e: return R.failed(msg="数据完整性错误") except Exception as e: logging.error(f"数据库异常: {str(e)}") return R.failed(msg="操作失败,请稍后重试") ```