Skip to content

第四章 架构设计 - 请求处理流程

4.1 请求处理全链路

一个完整的 HTTP 请求在 系统中的处理流程如下:

浏览器
    |
    | (1) 发起HTTP请求 (携带 Authorization: Bearer <token>)
    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_loginPermissionRequired 不是 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:<module>:<action>

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="操作失败,请稍后重试")

小蚂蚁云团队 · 提供技术支持