Files
xingrin/backend/apps/asset/serializers.py

292 lines
8.0 KiB
Python
Raw Normal View History

2025-12-12 18:04:57 +08:00
from rest_framework import serializers
from .models import Subdomain, WebSite, Directory, HostPortMapping, Endpoint, Vulnerability
from .models.snapshot_models import (
SubdomainSnapshot,
WebsiteSnapshot,
DirectorySnapshot,
EndpointSnapshot,
VulnerabilitySnapshot,
)
# 注意IPAddress 和 Port 模型已被重构为 HostPortMapping
# 以下是基于新架构的序列化器实现
# class PortSerializer(serializers.ModelSerializer):
# """端口序列化器"""
#
# class Meta:
# model = Port
# fields = ['number', 'service_name', 'description', 'is_uncommon']
class SubdomainSerializer(serializers.ModelSerializer):
"""子域名序列化器"""
class Meta:
model = Subdomain
fields = [
'id', 'name', 'discovered_at', 'target'
]
read_only_fields = ['id', 'discovered_at']
class SubdomainListSerializer(serializers.ModelSerializer):
"""子域名列表序列化器(用于扫描详情)"""
# 注意Subdomain 模型已简化,只保留核心字段
# cname, is_cdn, cdn_name 等字段已移至 SubdomainSnapshot
# ports 和 ip_addresses 关系已被重构为 HostPortMapping
class Meta:
model = Subdomain
fields = [
'id', 'name', 'discovered_at'
]
read_only_fields = ['id', 'discovered_at']
# class IPAddressListSerializer(serializers.ModelSerializer):
# """IP 地址列表序列化器"""
#
# subdomain = serializers.CharField(source='subdomain.name', allow_blank=True, default='')
# created_at = serializers.DateTimeField(read_only=True)
# ports = PortSerializer(many=True, read_only=True)
#
# class Meta:
# model = IPAddress
# fields = [
# 'id',
# 'ip',
# 'subdomain',
# 'reverse_pointer',
# 'created_at',
# 'ports',
# ]
# read_only_fields = fields
class WebSiteSerializer(serializers.ModelSerializer):
"""站点序列化器"""
subdomain = serializers.CharField(source='subdomain.name', allow_blank=True, default='')
class Meta:
model = WebSite
fields = [
'id',
'url',
'location',
'title',
'webserver',
'content_type',
'status_code',
'content_length',
'body_preview',
'tech',
'vhost',
'subdomain',
'discovered_at',
]
read_only_fields = fields
class VulnerabilitySerializer(serializers.ModelSerializer):
"""漏洞资产序列化器(按目标查看漏洞资产)。"""
class Meta:
model = Vulnerability
fields = [
'id',
'target',
'url',
'vuln_type',
'severity',
'source',
'cvss_score',
'description',
'raw_output',
'discovered_at',
]
read_only_fields = fields
class VulnerabilitySnapshotSerializer(serializers.ModelSerializer):
"""漏洞快照序列化器(用于扫描历史漏洞列表)。"""
class Meta:
model = VulnerabilitySnapshot
fields = [
'id',
'url',
'vuln_type',
'severity',
'source',
'cvss_score',
'description',
'raw_output',
'discovered_at',
]
read_only_fields = fields
class EndpointListSerializer(serializers.ModelSerializer):
"""端点列表序列化器(用于目标端点列表页)"""
# 将 GF 匹配模式映射为前端使用的 tags 字段
tags = serializers.ListField(
child=serializers.CharField(),
source='matched_gf_patterns',
read_only=True,
)
class Meta:
model = Endpoint
fields = [
'id',
'url',
'location',
'status_code',
'title',
'content_length',
'content_type',
'webserver',
'body_preview',
'tech',
'vhost',
'tags',
'discovered_at',
]
read_only_fields = fields
class DirectorySerializer(serializers.ModelSerializer):
"""目录序列化器"""
website_url = serializers.CharField(source='website.url', read_only=True)
discovered_at = serializers.DateTimeField(read_only=True)
class Meta:
model = Directory
fields = [
'id',
'url',
'status',
'content_length',
'words',
'lines',
'content_type',
'duration',
'website_url',
'discovered_at',
]
read_only_fields = fields
class IPAddressAggregatedSerializer(serializers.Serializer):
"""
IP 地址聚合序列化器
基于 HostPortMapping 模型 IP 聚合显示
- ip: IP 地址
- hosts: IP 关联的所有主机名列表
- ports: IP 关联的所有端口列表
- discovered_at: 首次发现时间
"""
ip = serializers.IPAddressField(read_only=True)
hosts = serializers.ListField(child=serializers.CharField(), read_only=True)
ports = serializers.ListField(child=serializers.IntegerField(), read_only=True)
discovered_at = serializers.DateTimeField(read_only=True)
# ==================== 快照序列化器 ====================
class SubdomainSnapshotSerializer(serializers.ModelSerializer):
"""子域名快照序列化器(用于扫描历史)"""
class Meta:
model = SubdomainSnapshot
fields = ['id', 'name', 'discovered_at']
read_only_fields = fields
class WebsiteSnapshotSerializer(serializers.ModelSerializer):
"""网站快照序列化器(用于扫描历史)"""
subdomain_name = serializers.CharField(source='subdomain.name', read_only=True)
webserver = serializers.CharField(source='web_server', read_only=True) # 映射字段名
status_code = serializers.IntegerField(source='status', read_only=True) # 映射字段名
class Meta:
model = WebsiteSnapshot
fields = [
'id',
'url',
'location',
'title',
'webserver', # 使用映射后的字段名
'content_type',
'status_code', # 使用映射后的字段名
'content_length',
'body_preview',
'tech',
'vhost',
'subdomain_name',
'discovered_at',
]
read_only_fields = fields
class DirectorySnapshotSerializer(serializers.ModelSerializer):
"""目录快照序列化器(用于扫描历史)"""
# DirectorySnapshot 当前不再关联 Website这里暂时将 website_url 映射为自身的 url保证字段兼容
website_url = serializers.CharField(source='url', read_only=True)
class Meta:
model = DirectorySnapshot
fields = [
'id',
'url',
'status',
'content_length',
'words',
'lines',
'content_type',
'duration',
'website_url',
'discovered_at',
]
read_only_fields = fields
class EndpointSnapshotSerializer(serializers.ModelSerializer):
"""端点快照序列化器(用于扫描历史)"""
# 将 GF 匹配模式映射为前端使用的 tags 字段
tags = serializers.ListField(
child=serializers.CharField(),
source='matched_gf_patterns',
read_only=True,
)
class Meta:
model = EndpointSnapshot
fields = [
'id',
'url',
'host',
'location',
'title',
'webserver',
'content_type',
'status_code',
'content_length',
'body_preview',
'tech',
'vhost',
'tags',
'discovered_at',
]
read_only_fields = fields