08ea5fbe98
添加用户管理视图、API和状态管理文件
282 lines
11 KiB
Python
282 lines
11 KiB
Python
"""
|
|
安全测试模块 - TDD Red阶段
|
|
|
|
测试SQL注入、XSS、CSRF等安全防护功能。
|
|
"""
|
|
|
|
import pytest
|
|
import allure
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
@allure.epic("核心框架")
|
|
@allure.feature("安全测试模块 - TDD Red阶段")
|
|
class TestSecurityModule:
|
|
"""安全测试模块测试类 - TDD Red阶段(期望失败)"""
|
|
|
|
@allure.title("测试SQL注入检测 - TDD Red阶段")
|
|
@allure.description("验证SQL注入攻击检测和防护 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_sql_injection_detection(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试SQL注入检测
|
|
|
|
预期结果:
|
|
- 能够检测常见的SQL注入攻击
|
|
- 返回检测结果和风险等级
|
|
"""
|
|
from core.security import SQLInjectionDetector
|
|
|
|
with allure.step("Step 1: 创建SQL注入检测器"):
|
|
detector = SQLInjectionDetector()
|
|
allure.attach("✅ 创建SQL注入检测器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试常见SQL注入攻击"):
|
|
test_cases = [
|
|
("' OR '1'='1", True),
|
|
("'; DROP TABLE users; --", True),
|
|
("1' AND 1=1 --", True),
|
|
("normal_username", False),
|
|
("user@example.com", False),
|
|
]
|
|
|
|
for input_str, expected in test_cases:
|
|
result = detector.detect(input_str)
|
|
allure.attach(
|
|
f"输入: {input_str}, 检测结果: {result.is_injection}, 期望: {expected}",
|
|
"步骤2",
|
|
allure.attachment_type.TEXT
|
|
)
|
|
assert result.is_injection == expected, f"检测失败: {input_str}"
|
|
|
|
@allure.title("测试XSS攻击检测 - TDD Red阶段")
|
|
@allure.description("验证XSS攻击检测和防护 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_xss_detection(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试XSS攻击检测
|
|
|
|
预期结果:
|
|
- 能够检测常见的XSS攻击
|
|
- 支持多种XSS类型检测
|
|
"""
|
|
from core.security import XSSDetector
|
|
|
|
with allure.step("Step 1: 创建XSS检测器"):
|
|
detector = XSSDetector()
|
|
allure.attach("✅ 创建XSS检测器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试常见XSS攻击"):
|
|
test_cases = [
|
|
("<script>alert('xss')</script>", True),
|
|
("<img src=x onerror=alert('xss')>", True),
|
|
("javascript:alert('xss')", True),
|
|
("<div>正常内容</div>", False),
|
|
("普通文本", False),
|
|
]
|
|
|
|
for input_str, expected in test_cases:
|
|
result = detector.detect(input_str)
|
|
allure.attach(
|
|
f"输入: {input_str[:30]}..., 检测结果: {result.is_xss}, 期望: {expected}",
|
|
"步骤2",
|
|
allure.attachment_type.TEXT
|
|
)
|
|
assert result.is_xss == expected, f"检测失败: {input_str}"
|
|
|
|
@allure.title("测试CSRF防护 - TDD Red阶段")
|
|
@allure.description("验证CSRF防护机制 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_csrf_protection(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试CSRF防护
|
|
|
|
预期结果:
|
|
- 能够生成和验证CSRF Token
|
|
- 防止跨站请求伪造攻击
|
|
"""
|
|
from core.security import CSRFProtector
|
|
|
|
with allure.step("Step 1: 创建CSRF防护器"):
|
|
protector = CSRFProtector()
|
|
allure.attach("✅ 创建CSRF防护器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 生成CSRF Token"):
|
|
token = protector.generate_token("user123")
|
|
allure.attach(f"生成Token: {token[:20]}...", "步骤2", allure.attachment_type.TEXT)
|
|
assert token is not None and len(token) > 0, "Token生成失败"
|
|
|
|
with allure.step("Step 3: 验证有效Token"):
|
|
is_valid = protector.validate_token("user123", token)
|
|
allure.attach(f"验证结果: {is_valid}", "步骤3", allure.attachment_type.TEXT)
|
|
assert is_valid is True, "有效Token验证失败"
|
|
|
|
with allure.step("Step 4: 验证无效Token"):
|
|
is_valid = protector.validate_token("user123", "invalid_token")
|
|
allure.attach(f"验证结果: {is_valid}", "步骤4", allure.attachment_type.TEXT)
|
|
assert is_valid is False, "无效Token应该验证失败"
|
|
|
|
@allure.title("测试输入净化 - TDD Red阶段")
|
|
@allure.description("验证输入数据净化功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_input_sanitization(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试输入净化
|
|
|
|
预期结果:
|
|
- 能够移除或转义危险字符
|
|
- 保持合法输入不变
|
|
"""
|
|
from core.security import InputSanitizer
|
|
|
|
with allure.step("Step 1: 创建输入净化器"):
|
|
sanitizer = InputSanitizer()
|
|
allure.attach("✅ 创建输入净化器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试HTML净化"):
|
|
test_cases = [
|
|
("<script>alert('xss')</script>", ""),
|
|
("<p>正常段落</p>", "<p>正常段落</p>"),
|
|
("<img src=x onerror=alert('xss')>", "<img src=x>"),
|
|
]
|
|
|
|
for input_str, expected in test_cases:
|
|
result = sanitizer.sanitize_html(input_str)
|
|
allure.attach(
|
|
f"输入: {input_str[:30]}..., 输出: {result[:30]}...",
|
|
"步骤2",
|
|
allure.attachment_type.TEXT
|
|
)
|
|
|
|
@allure.title("测试密码强度检查 - TDD Red阶段")
|
|
@allure.description("验证密码强度评估功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_password_strength(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试密码强度检查
|
|
|
|
预期结果:
|
|
- 能够评估密码强度
|
|
- 返回强度等级和建议
|
|
"""
|
|
from core.security import PasswordStrengthChecker
|
|
|
|
with allure.step("Step 1: 创建密码强度检查器"):
|
|
checker = PasswordStrengthChecker()
|
|
allure.attach("✅ 创建密码强度检查器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试不同强度密码"):
|
|
test_cases = [
|
|
("123", "weak"),
|
|
("password", "weak"),
|
|
("Password123", "medium"),
|
|
("P@ssw0rd!2024", "strong"),
|
|
]
|
|
|
|
for password, expected_min_strength in test_cases:
|
|
result = checker.check(password)
|
|
allure.attach(
|
|
f"密码: {password[:10]}..., 强度: {result.strength}",
|
|
"步骤2",
|
|
allure.attachment_type.TEXT
|
|
)
|
|
assert result.score > 0, "密码评分应该大于0"
|
|
|
|
@allure.title("测试安全头部设置 - TDD Red阶段")
|
|
@allure.description("验证HTTP安全头部设置 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_security_headers(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试安全头部设置
|
|
|
|
预期结果:
|
|
- 能够生成安全HTTP头部
|
|
- 包含必要的安全策略
|
|
"""
|
|
from core.security import SecurityHeaders
|
|
|
|
with allure.step("Step 1: 创建安全头部生成器"):
|
|
headers = SecurityHeaders()
|
|
allure.attach("✅ 创建安全头部生成器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 获取安全头部"):
|
|
security_headers = headers.get_headers()
|
|
allure.attach(f"安全头部: {security_headers}", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
assert "X-Content-Type-Options" in security_headers, "缺少X-Content-Type-Options"
|
|
assert "X-Frame-Options" in security_headers, "缺少X-Frame-Options"
|
|
assert "X-XSS-Protection" in security_headers, "缺少X-XSS-Protection"
|
|
|
|
@allure.title("测试安全审计日志 - TDD Red阶段")
|
|
@allure.description("验证安全事件审计日志 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_security_audit_log(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试安全审计日志
|
|
|
|
预期结果:
|
|
- 能够记录安全事件
|
|
- 支持查询和统计
|
|
"""
|
|
from core.security import SecurityAuditLogger
|
|
|
|
with allure.step("Step 1: 创建安全审计日志器"):
|
|
logger = SecurityAuditLogger()
|
|
allure.attach("✅ 创建安全审计日志器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 记录安全事件"):
|
|
logger.log_event(
|
|
event_type="SQL_INJECTION_ATTEMPT",
|
|
source_ip="192.168.1.1",
|
|
details={"input": "' OR '1'='1"}
|
|
)
|
|
logger.log_event(
|
|
event_type="XSS_ATTEMPT",
|
|
source_ip="192.168.1.2",
|
|
details={"input": "<script>alert('xss')</script>"}
|
|
)
|
|
allure.attach("✅ 记录2个安全事件", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 查询安全事件"):
|
|
events = logger.get_events()
|
|
allure.attach(f"事件数量: {len(events)}", "步骤3", allure.attachment_type.TEXT)
|
|
assert len(events) == 2, "应该有2个安全事件"
|
|
|
|
@allure.title("测试综合安全扫描 - TDD Red阶段")
|
|
@allure.description("验证综合安全扫描功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_comprehensive_security_scan(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试综合安全扫描
|
|
|
|
预期结果:
|
|
- 能够扫描多种安全威胁
|
|
- 返回详细的扫描报告
|
|
"""
|
|
from core.security import SecurityScanner
|
|
|
|
with allure.step("Step 1: 创建安全扫描器"):
|
|
scanner = SecurityScanner()
|
|
allure.attach("✅ 创建安全扫描器", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 扫描测试数据"):
|
|
test_data = {
|
|
"username": "' OR '1'='1",
|
|
"comment": "<script>alert('xss')</script>",
|
|
"email": "test@example.com",
|
|
}
|
|
|
|
report = scanner.scan(test_data)
|
|
allure.attach(f"扫描报告: {report}", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
assert report.total_scanned > 0, "应该扫描了数据"
|
|
assert len(report.threats) > 0, "应该检测到威胁"
|