Files
whale-town/tests/test_security_manager.gd
2025-12-06 17:33:14 +08:00

328 lines
10 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Node
## 安全管理器测试
## 测试安全验证、输入过滤和防护措施
var security_manager: SecurityManager
func _ready():
print("=== 安全管理器测试开始 ===")
# 运行所有测试
test_validate_input_valid()
test_validate_input_invalid()
test_malicious_content_detection()
test_sql_injection_detection()
test_excessive_repetition_detection()
test_input_sanitization()
test_message_format_validation()
test_session_management()
test_failed_attempt_recording()
test_security_statistics()
await test_session_timeout()
test_edge_cases()
print("=== 安全管理器测试完成 ===")
func setup_test():
## 每个测试前的设置
security_manager = SecurityManager.new()
func cleanup_test():
## 每个测试后的清理
if security_manager:
security_manager.queue_free()
security_manager = null
## 测试输入验证 - 有效输入
func test_validate_input_valid():
## 测试有效输入的验证
print("\n--- 测试输入验证 - 有效输入 ---")
setup_test()
# 测试有效用户名
var result = SecurityManager.validate_input("TestUser123", "username")
assert(result.valid, "Valid username should pass validation")
assert(result.sanitized == "TestUser123", "Valid username should not be modified")
# 测试有效角色名
result = SecurityManager.validate_input("MyCharacter", "character_name")
assert(result.valid, "Valid character name should pass validation")
assert(result.sanitized == "MyCharacter", "Valid character name should not be modified")
# 测试有效消息
result = SecurityManager.validate_input("Hello, world!", "message")
assert(result.valid, "Valid message should pass validation")
assert(result.sanitized == "Hello, world!", "Valid message should not be modified")
print("✅ 有效输入验证测试通过")
cleanup_test()
## 测试输入验证 - 无效输入
func test_validate_input_invalid():
## 测试无效输入的验证
print("\n--- 测试输入验证 - 无效输入 ---")
setup_test()
# 测试空输入
var result = SecurityManager.validate_input("", "username")
assert(not result.valid, "Empty username should fail validation")
assert(result.error.length() > 0, "Should provide error message")
# 测试过长输入
var long_string = "a".repeat(100)
result = SecurityManager.validate_input(long_string, "character_name")
assert(not result.valid, "Overly long character name should fail validation")
# 测试过短角色名
result = SecurityManager.validate_input("a", "character_name")
assert(not result.valid, "Too short character name should fail validation")
print("✅ 无效输入验证测试通过")
cleanup_test()
## 测试恶意内容检测
func test_malicious_content_detection():
## 测试恶意内容检测
print("\n--- 测试恶意内容检测 ---")
setup_test()
# 测试脚本注入
var malicious_inputs = [
"<script>alert('xss')</script>",
"javascript:alert('xss')",
"onload=alert('xss')",
"eval(malicious_code)",
"document.cookie"
]
for malicious_input in malicious_inputs:
var result = SecurityManager.validate_input(malicious_input, "message")
assert(not result.valid, "Malicious input should be rejected: " + malicious_input)
assert(result.error.contains("不安全内容"), "Should indicate unsafe content")
print("✅ 恶意内容检测测试通过")
cleanup_test()
## 测试SQL注入检测
func test_sql_injection_detection():
## 测试SQL注入检测
print("\n--- 测试SQL注入检测 ---")
setup_test()
var injection_inputs = [
"'; DROP TABLE users; --",
"' OR '1'='1",
"UNION SELECT * FROM passwords",
"INSERT INTO users VALUES"
]
for injection_input in injection_inputs:
var result = SecurityManager.validate_input(injection_input, "message")
assert(not result.valid, "SQL injection should be rejected: " + injection_input)
print("✅ SQL注入检测测试通过")
cleanup_test()
## 测试过度重复字符检测
func test_excessive_repetition_detection():
## 测试过度重复字符检测
print("\n--- 测试过度重复字符检测 ---")
setup_test()
# 创建70%重复字符的字符串
var repetitive_string = "a".repeat(70) + "b".repeat(30)
var result = SecurityManager.validate_input(repetitive_string, "message")
assert(not result.valid, "Excessive repetition should be rejected")
assert(result.error.contains("重复字符"), "Should indicate repetition issue")
print("✅ 过度重复字符检测测试通过")
cleanup_test()
## 测试输入清理
func test_input_sanitization():
## 测试输入清理功能
print("\n--- 测试输入清理 ---")
setup_test()
# 测试HTML标签移除
var html_input = "Hello <b>world</b>!"
var sanitized = SecurityManager.sanitize_input(html_input)
assert(not sanitized.contains("<b>"), "HTML tags should be removed")
assert(not sanitized.contains("</b>"), "HTML tags should be removed")
assert(sanitized.contains("Hello"), "Text content should be preserved")
assert(sanitized.contains("world"), "Text content should be preserved")
# 测试多余空格处理
var spaced_input = "Hello world !"
sanitized = SecurityManager.sanitize_input(spaced_input)
assert(not sanitized.contains(" "), "Multiple spaces should be reduced")
assert(sanitized.contains("Hello world"), "Should contain single spaces")
print("✅ 输入清理测试通过")
cleanup_test()
## 测试消息格式验证
func test_message_format_validation():
## 测试网络消息格式验证
print("\n--- 测试消息格式验证 ---")
setup_test()
# 测试有效消息
var valid_message = {
"type": "auth_request",
"data": {"username": "test"},
"timestamp": Time.get_unix_time_from_system()
}
assert(SecurityManager.validate_message_format(valid_message), "Valid message should pass")
# 测试缺少字段的消息
var invalid_message = {
"type": "auth_request"
# 缺少 data 和 timestamp
}
assert(not SecurityManager.validate_message_format(invalid_message), "Invalid message should fail")
# 测试无效消息类型
var invalid_type_message = {
"type": "malicious_type",
"data": {},
"timestamp": Time.get_unix_time_from_system()
}
assert(not SecurityManager.validate_message_format(invalid_type_message), "Invalid message type should fail")
# 测试时间戳过旧
var old_message = {
"type": "auth_request",
"data": {},
"timestamp": Time.get_unix_time_from_system() - 400 # 超过5分钟
}
assert(not SecurityManager.validate_message_format(old_message), "Old timestamp should fail")
print("✅ 消息格式验证测试通过")
cleanup_test()
## 测试会话管理
func test_session_management():
## 测试会话管理功能
print("\n--- 测试会话管理 ---")
setup_test()
# 创建会话
var session_token = security_manager.create_session("client123", "testuser")
assert(session_token.length() > 0, "Should generate session token")
# 验证会话
assert(security_manager.validate_session(session_token), "New session should be valid")
# 使会话无效
security_manager.invalidate_session(session_token)
assert(not security_manager.validate_session(session_token), "Invalidated session should be invalid")
print("✅ 会话管理测试通过")
cleanup_test()
## 测试失败尝试记录
func test_failed_attempt_recording():
## 测试失败尝试记录和锁定机制
print("\n--- 测试失败尝试记录 ---")
setup_test()
var client_id = "test_client"
# 记录多次失败尝试
for i in range(4): # 4次失败还未达到锁定阈值
var should_lock = security_manager.record_failed_attempt(client_id)
assert(not should_lock, "Should not lock before reaching max attempts")
# 第5次失败应该触发锁定
var should_lock = security_manager.record_failed_attempt(client_id)
assert(should_lock, "Should lock after max failed attempts")
# 检查锁定状态
assert(security_manager.is_locked(client_id), "Client should be locked")
# 清除失败尝试
security_manager.clear_failed_attempts(client_id)
assert(not security_manager.is_locked(client_id), "Client should be unlocked after clearing attempts")
print("✅ 失败尝试记录测试通过")
cleanup_test()
## 测试安全统计
func test_security_statistics():
## 测试安全统计功能
print("\n--- 测试安全统计 ---")
setup_test()
# 创建一些会话和失败尝试
security_manager.create_session("client1", "user1")
security_manager.create_session("client2", "user2")
security_manager.record_failed_attempt("client3")
var stats = security_manager.get_security_stats()
assert(stats.has("active_sessions"), "Stats should include active sessions")
assert(stats.has("failed_attempts"), "Stats should include failed attempts")
assert(stats.has("locked_clients"), "Stats should include locked clients")
assert(stats.active_sessions == 2, "Should have 2 active sessions")
assert(stats.failed_attempts == 1, "Should have 1 failed attempt record")
print("✅ 安全统计测试通过")
cleanup_test()
## 测试会话超时
func test_session_timeout():
## 测试会话超时机制
print("\n--- 测试会话超时 ---")
setup_test()
# 创建会话
var session_token = security_manager.create_session("client123", "testuser")
# 修改会话超时时间为很短的时间进行测试
security_manager.session_timeout = 0.1 # 0.1秒
# 等待超时
await get_tree().create_timer(0.2).timeout
# 验证会话应该已过期
assert(not security_manager.validate_session(session_token), "Session should expire after timeout")
print("✅ 会话超时测试通过")
cleanup_test()
## 测试边界情况
func test_edge_cases():
## 测试边界情况
print("\n--- 测试边界情况 ---")
setup_test()
# 测试null输入
var result = SecurityManager.validate_input(null, "username")
assert(not result.valid, "Null input should be rejected")
# 测试空白字符输入
result = SecurityManager.validate_input(" ", "character_name")
assert(not result.valid, "Whitespace-only input should be rejected")
# 测试边界长度
var min_length_name = "ab" # 最小长度
result = SecurityManager.validate_input(min_length_name, "character_name")
assert(result.valid, "Minimum length name should be valid")
var max_length_name = "a".repeat(20) # 最大长度
result = SecurityManager.validate_input(max_length_name, "character_name")
assert(result.valid, "Maximum length name should be valid")
print("✅ 边界情况测试通过")
cleanup_test()
## 断言函数
func assert(condition: bool, message: String):
## 简单的断言函数
if not condition:
push_error("断言失败: " + message)
print("" + message)
else:
print("" + message)