【Dv3Admin】工具请求配置文件解析

发布于:2025-06-01 ⋅ 阅读:(28) ⋅ 点赞:(0)

Web系统中高效提取请求信息是提升开发效率与安全审计的重要手段。通过封装常用请求处理逻辑,可避免重复造轮子,标准化请求数据的收集与分析过程,支撑上层日志、监控与风控系统的建设。

本文围绕 request_util.py 源码,解析如何在 Django+DRF 项目中提取用户、IP、请求参数、设备信息,并结合外部接口实现地理位置分析。通过工具化封装,统一了数据提取逻辑,提升了项目整体的可维护性与拓展性。

request_util.py

系统基于 Django 和 DRF 框架开发,dvadmin/utils/request_util.py 作为请求工具模块,封装了对 Request 请求对象的常用操作。通过标准化提取请求用户、IP地址、参数、路径、浏览器信息、系统信息等数据,提升开发效率和代码复用性,同时支撑后台登录日志记录、行为审计等功能模块。

项目特点 描述
技术栈 Django + DRF
功能定位 统一处理请求数据提取、用户认证、IP分析、日志保存
辅助功能 提供 IP 地理位置分析与请求设备信息提取
设计模式 工具类封装,便于全局调用

dvadmin/utils/request_util.py 提供一系列针对 HTTP Request 对象的辅助函数,包括提取当前请求用户、IP 地址、请求参数、标准化路径、解析浏览器和操作系统信息。同时还内置了与外部接口对接的 IP 地址分析功能,用于获取详细的地理位置数据,并提供 save_login_log 方法自动记录登录日志。这些工具函数统一了系统内部对于请求数据的处理方式,降低了开发成本和维护难度。

模块职责 说明
用户获取 自动认证并返回请求关联的用户对象
请求IP提取 从请求头中智能提取真实客户端IP地址
请求参数提取 合并GET、POST、Body数据为统一格式
路径标准化处理 支持动态ID占位标准化请求路径,便于日志和权限管理
浏览器与系统识别 通过 User-Agent 分析浏览器和操作系统信息
IP地理位置分析 基于外部API接口解析IP地址详细地理信息
登录日志保存 自动记录用户登录时的环境数据和地理信息

在用户认证、行为日志、审计日志、异常分析等场景中,需要频繁提取用户信息、IP 地址、请求参数。通过使用 dvadmin/utils/request_util.py 中封装的方法,可以标准化这些操作,并且降低代码重复。适用于统一收集请求元数据、记录安全日志、分析访问来源等应用场景,确保后台数据链完整可靠。

使用场景 说明
后台统一提取登录用户 支持未认证时手动认证 JWT Token,避免异常
API 请求日志审计 提取访问路径、参数、IP,用于日志记录与审计分析
登录地理位置统计与风控 分析IP归属地,辅助判断异常登录行为
异常行为追踪 通过浏览器、系统、IP信息综合识别异常访问模式
统一保存用户登录日志 自动记录详细设备信息和地理数据,便于后台管理与统计分析

项目源码解析

获取请求用户对象

用于从 request 中提取用户对象,如果 request.user 未认证,则尝试手动通过 JWT 认证机制进行认证,最终保证返回一个用户对象或匿名用户对象。依赖 DRF SimpleJWT 的认证模块,适配有登录状态检查的接口场景。

def get_request_user(request):
    user: AbstractBaseUser = getattr(request, 'user', None)
    if user and user.is_authenticated:
        return user
    try:
        user, token = JWTAuthentication().authenticate(request)
    except Exception:
        pass
    return user or AnonymousUser()

获取请求来源 IP 地址

提取请求头中的 HTTP_X_FORWARDED_FORREMOTE_ADDR 信息作为客户端 IP 地址,适配常见反向代理部署场景。该方法对于登录日志、IP 限制、安全防护模块非常关键。

def get_request_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
        return ip
    ip = request.META.get('REMOTE_ADDR', '') or getattr(request, 'request_ip', None)
    return ip or 'unknown'

获取请求参数数据

统一提取 GET、POST、Body 传递的参数,支持 JSON 格式解析,保证接口内部无论何种方式传参都可以标准化获取数据,提升接口兼容性。

def get_request_data(request):
    request_data = getattr(request, 'request_data', None)
    if request_data:
        return request_data
    data: dict = {**request.GET.dict(), **request.POST.dict()}
    if not data:
        try:
            body = request.body
            if body:
                data = json.loads(body)
        except Exception:
            pass
        if not isinstance(data, dict):
            data = {'data': data}
    return data

动态生成统一请求路径

将请求路径中的具体参数(如 ID)替换成 {id} 通配符,规范化日志或权限规则中记录的接口路径格式,保证路径识别的一致性。

def get_request_path(request, *args, **kwargs):
    request_path = getattr(request, 'request_path', None)
    if request_path:
        return request_path
    values = []
    for arg in args:
        if isinstance(arg, str):
            values.append(arg)
        elif isinstance(arg, (tuple, set, list, dict)):
            values.extend(arg if not isinstance(arg, dict) else arg.values())
    if not values:
        return request.path
    path: str = request.path
    for value in values:
        path = path.replace('/' + value, '/{id}')
    return path

规范化请求路径

利用 Django ResolverMatch 对象,根据路径参数动态替换生成统一规范格式,适用于更复杂的动态路径匹配,如批量对象访问接口的标准化处理。

def get_request_canonical_path(request):
    request_path = getattr(request, 'request_canonical_path', None)
    if request_path:
        return request_path
    path: str = request.path
    resolver_match: ResolverMatch = request.resolver_match
    for value in resolver_match.args:
        path = path.replace(f"/{value}", "/{id}")
    for key, value in resolver_match.kwargs.items():
        if key == 'pk':
            path = path.replace(f"/{value}", "/{id}")
        else:
            path = path.replace(f"/{value}", f"/{{{key}}}")
    return path

获取浏览器信息

解析 User-Agent 请求头信息,提取访问设备所使用的浏览器类型,用于登录日志、访问分析、设备识别等场景。

def get_browser(request):
    ua_string = request.META['HTTP_USER_AGENT']
    user_agent = parse(ua_string)
    return user_agent.get_browser()

获取操作系统信息

通过解析 User-Agent 字符串,提取客户端设备的操作系统信息,辅助进行平台适配、异常分析或访问统计。

def get_os(request):
    ua_string = request.META['HTTP_USER_AGENT']
    user_agent = parse(ua_string)
    return user_agent.get_os()

获取模型描述信息

根据 QuerySet、视图或模型实例动态提取 Django 模型的 verbose_name 属性,用于日志、审计、权限等系统内部描述展示。

def get_verbose_name(queryset=None, view=None, model=None):
    try:
        if queryset is not None and hasattr(queryset, 'model'):
            model = queryset.model
        elif view and hasattr(view.get_queryset(), 'model'):
            model = view.get_queryset().model
        elif view and hasattr(view.get_serializer(), 'Meta') and hasattr(view.get_serializer().Meta, 'model'):
            model = view.get_serializer().Meta.model
        if model:
            return getattr(model, '_meta').verbose_name
    except Exception:
        pass
    return model if model else ""

获取 IP 地址地理信息

调用外部 IP 解析服务接口,根据 IP 地址返回详细地理位置信息,包括国家、省份、城市、运营商等数据,增强登录安全与统计分析能力。

def get_ip_analysis(ip):
    data = {
        "continent": "", "country": "", "province": "", "city": "", "district": "",
        "isp": "", "area_code": "", "country_english": "", "country_code": "",
        "longitude": "", "latitude": ""
    }
    if ip != 'unknown' and ip:
        if getattr(settings, 'ENABLE_LOGIN_ANALYSIS_LOG', True):
            try:
                res = requests.get(url='https://ip.django-vue-admin.com/ip/analysis', params={"ip": ip}, timeout=5)
                if res.status_code == 200:
                    res_data = res.json()
                    if res_data.get('code') == 0:
                        data = res_data.get('data')
                return data
            except Exception as e:
                print(e)
    return data

保存登录日志记录

收集用户登录时的各种信息,如 IP、设备、地理位置,并将其写入系统登录日志表 LoginLog,用于系统审计、行为分析和异常检测。

def save_login_log(request):
    ip = get_request_ip(request=request)
    analysis_data = get_ip_analysis(ip)
    analysis_data['username'] = request.user.username
    analysis_data['ip'] = ip
    analysis_data['agent'] = str(parse(request.META['HTTP_USER_AGENT']))
    analysis_data['browser'] = get_browser(request)
    analysis_data['os'] = get_os(request)
    analysis_data['creator_id'] = request.user.id
    analysis_data['dept_belong_id'] = getattr(request.user, 'dept_id', '')
    LoginLog.objects.create(**analysis_data)

应用案例

请求信息提取与日志记录机制在后台管理系统中的应用

在后台管理系统中,高效、标准化地提取用户、IP、请求参数、设备信息等请求数据是提升安全性和开发效率的关键。通过 dvadmin/utils/request_util.py 模块,系统实现了对 HTTP 请求的全面封装与提取,确保在各类场景下能够统一获取请求相关信息。该模块不仅支持用户认证、请求参数提取、IP 地址分析,还通过调用外部接口分析 IP 地理位置,为登录日志和安全审计提供基础数据。

功能点 内容描述
场景需求 高效、标准化地提取 HTTP 请求相关信息(如用户、IP、请求参数、设备信息等),提升系统安全性与开发效率,支持安全审计与风控分析。
核心模块 dvadmin/utils/request_util.py:封装 HTTP 请求相关信息提取功能,统一获取请求数据,便于日志记录与安全分析。
支持功能 - 用户认证提取:解析请求中的用户认证信息,包括用户身份与角色。
- 请求参数提取:支持 GET 和 POST 参数的统一解析与提取,便于后续业务处理。
- IP 地址分析:提取客户端 IP 地址,并支持调用外部服务进行 IP 地理位置分析。
- 设备信息获取:解析客户端 User-Agent 信息,识别操作系统、浏览器等设备信息。
实现机制 - 封装 Django 请求对象:通过对 Django HttpRequest 对象的扩展,统一访问请求数据。
- 外部接口调用:通过集成第三方 API 服务(如 IP 地理位置查询),提升 IP 地址分析能力。

在实际开发中,管理员登录、操作行为、IP 源分析等关键信息都通过该模块统一提取并保存到日志系统,为后续的风控和异常行为分析提供重要依据。以下是基于该模块实现的具体业务功能与操作。

功能点 内容描述
应用场景 - 用户登录日志:记录用户登录时的 IP 地址、设备信息,用于安全审计与异常行为分析。
- 操作行为审计:提取管理员操作请求中的详细信息,存入日志系统,追踪操作来源与行为。
- 风控分析:结合 IP 地址地理位置数据,识别异常登录或操作行为。
优势 - 提供统一的数据提取接口,减少重复开发工作。
- 支持外部服务集成,增强数据分析能力。
- 提升系统安全性与可观测性。
扩展能力 - 支持更多设备信息字段的解析(如分辨率、网络类型)。
- 集成更加丰富的外部分析服务,如风险评分与威胁情报数据。

请求数据提取与日志记录操作示例

在每次用户登录时,系统需要记录用户信息、设备信息以及登录来源的地理位置。通过调用 save_login_log 函数,自动提取当前请求的用户信息、设备类型、操作系统、IP 地址及其地理位置信息,并存储到系统的登录日志表中。代码示例如下:

def save_login_log(request):
    ip = get_request_ip(request=request)
    analysis_data = get_ip_analysis(ip)
    analysis_data['username'] = request.user.username
    analysis_data['ip'] = ip
    analysis_data['agent'] = str(parse(request.META['HTTP_USER_AGENT']))
    analysis_data['browser'] = get_browser(request)
    analysis_data['os'] = get_os(request)
    analysis_data['creator_id'] = request.user.id
    analysis_data['dept_belong_id'] = getattr(request.user, 'dept_id', '')
    LoginLog.objects.create(**analysis_data)

此函数将用户登录时的详细信息存入 LoginLog 表,为后续的审计和风控提供数据支持。

动态获取请求参数与标准化路径

在 API 请求中,获取请求的参数和路径是常见需求。通过 get_request_dataget_request_path 函数,能够动态提取请求参数并规范化路径,简化日志记录和权限管理的复杂度。例如,在某个接口中,前端传递了 user_id,系统自动将其替换为 {id},实现路径的标准化,确保一致的日志记录格式。

def get_request_path(request, *args, **kwargs):
    request_path = getattr(request, 'request_path', None)
    if request_path:
        return request_path
    values = []
    for arg in args:
        if isinstance(arg, str):
            values.append(arg)
        elif isinstance(arg, (tuple, set, list, dict)):
            values.extend(arg if not isinstance(arg, dict) else arg.values())
    if not values:
        return request.path
    path: str = request.path
    for value in values:
        path = path.replace('/' + value, '/{id}')
    return path

这使得在日志记录时,无论路径中含有何种具体参数,最终记录的日志路径都统一为 {id} 格式,提升了日志的一致性与可追溯性。

请求来源 IP 地址与地理信息分析

IP 地址分析功能可以帮助系统识别用户的登录地理位置,通过 get_ip_analysis 函数调用外部 API 服务获取详细的地理位置数据。在处理登录日志时,可以自动补充如国家、省份、城市等信息,提升日志的业务可读性,帮助风控系统识别潜在风险。

def get_ip_analysis(ip):
    data = {
        "continent": "", "country": "", "province": "", "city": "", "district": "",
        "isp": "", "area_code": "", "country_english": "", "country_code": "",
        "longitude": "", "latitude": ""
    }
    if ip != 'unknown' and ip:
        try:
            res = requests.get(url='https://ip.django-vue-admin.com/ip/analysis', params={"ip": ip}, timeout=5)
            if res.status_code == 200:
                res_data = res.json()
                if res_data.get('code') == 0:
                    data = res_data.get('data')
        except Exception as e:
            print(e)
    return data

用户与设备信息解析

通过 get_browserget_os 函数提取请求头中的 User-Agent 信息,识别用户访问设备的浏览器类型和操作系统信息,便于后期日志分析和异常行为识别:

def get_browser(request):
    ua_string = request.META['HTTP_USER_AGENT']
    user_agent = parse(ua_string)
    return user_agent.get_browser()

def get_os(request):
    ua_string = request.META['HTTP_USER_AGENT']
    user_agent = parse(ua_string)
    return user_agent.get_os()

这使得在进行安全审计时,能够综合浏览器、操作系统、IP 地址等多维度信息识别用户的访问行为,帮助系统发现潜在的异常访问模式。

通过 dvadmin/utils/request_util.py 模块的封装,系统实现了高效、标准化的请求数据提取和日志记录,提升了开发效率和安全性。在后台管理平台中,能够快速集成这些功能,提供灵活的接口日志、监控、风控功能,并为后续的系统扩展和维护提供了便利。

总结

模块以独立工具函数方式封装,覆盖用户识别、IP提取、参数解析、路径标准化等核心功能,减少业务系统中的冗余代码。结合外部API完成IP地理信息补充,提升日志的业务可读性。统一的请求处理逻辑,方便在认证、日志、审计等多个场景中直接调用。

IP地址分析功能依赖外部接口,存在可用性风险且异常处理较弱。请求参数提取逻辑在复杂场景下兼容性不足,异常捕获范围过大。浏览器与系统识别基于 User-Agent 解析库,存在识别准确率波动问题。整体模块缺少缓存与限频机制,存在一定性能优化空间。


网站公告

今日签到

点亮在社区的每一天
去签到