Files

280 lines
8.3 KiB
Python

"""
认证安全测试套件
测试范围:
1. 密码安全测试
2. 登录安全测试
3. 会话管理测试
4. 权限验证测试
5. 暴力破解防护测试
作者: 张翔
日期: 2026-04-01
"""
import pytest
import time
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from config.settings import settings
@pytest.mark.security
@pytest.mark.asyncio
class TestAuthenticationSecurity:
"""认证安全测试类"""
async def test_password_strength_validation(self, authenticated_client):
"""
SEC-AUTH-01: 密码强度验证
验证点:
1. 弱密码被拒绝
2. 密码复杂度要求
3. 密码长度要求
"""
user_api = UserAPI(authenticated_client)
weak_passwords = [
"123456",
"password",
"admin",
"qwerty",
"abc123",
"111111",
"1234567890",
"password123"
]
for weak_pwd in weak_passwords:
user_data = {
"username": f"weak_pwd_test_{weak_pwd}",
"password": weak_pwd,
"email": f"weak_{weak_pwd}@test.com",
"phone": "13800138000",
"status": 1
}
response = await user_api.create_user(user_data)
assert response.status_code in [400, 422], \
f"弱密码 '{weak_pwd}' 应被拒绝"
async def test_password_hashing(self, authenticated_client):
"""
SEC-AUTH-02: 密码哈希验证
验证点:
1. 密码不以明文存储
2. 使用BCrypt或其他安全哈希
3. 每次哈希结果不同(盐值)
"""
user_api = UserAPI(authenticated_client)
auth_api = AuthAPI(authenticated_client)
user_data = {
"username": "hash_test_user",
"password": "Test123!@#",
"email": "hash_test@test.com",
"phone": "13800138000",
"status": 1
}
response = await user_api.create_user(user_data)
if response.status_code in [201, 200]:
user_id = response.json().get("id")
login_response = await auth_api.login(
user_data["username"],
user_data["password"]
)
assert login_response.status_code == 200, "密码验证失败"
await user_api.delete_user(user_id)
async def test_brute_force_protection(self, authenticated_client):
"""
SEC-AUTH-03: 暴力破解防护
验证点:
1. 多次失败登录被限制
2. 账户锁定机制
3. 登录失败提示不泄露信息
"""
auth_api = AuthAPI(authenticated_client)
failed_attempts = 0
max_attempts = 10
for i in range(max_attempts):
response = await auth_api.login("admin", "wrong_password_123")
if response.status_code == 429:
assert True, "暴力破解防护生效"
return
elif response.status_code == 401:
failed_attempts += 1
else:
break
assert failed_attempts >= 3, \
"应实施暴力破解防护(至少3次失败后限制)"
async def test_session_timeout(self, authenticated_client):
"""
SEC-AUTH-04: 会话超时测试
验证点:
1. Token有过期时间
2. 过期Token无法使用
3. 会话自动失效
"""
auth_api = AuthAPI(authenticated_client)
user_api = UserAPI(authenticated_client)
login_response = await auth_api.login("admin", "admin123")
token = login_response.json().get("token")
import jwt
decoded = jwt.decode(token, options={"verify_signature": False})
assert "exp" in decoded, "Token应包含过期时间"
exp_time = decoded["exp"]
current_time = time.time()
assert exp_time > current_time, "Token不应已过期"
assert exp_time - current_time <= 86400, "Token有效期不应超过24小时"
async def test_concurrent_session_handling(self, authenticated_client):
"""
SEC-AUTH-05: 并发会话处理
验证点:
1. 支持并发登录
2. 或限制并发会话数
3. 会话隔离
"""
auth_api = AuthAPI(authenticated_client)
login_responses = []
for i in range(3):
response = await auth_api.login("admin", "admin123")
login_responses.append(response)
successful_logins = sum(
1 for r in login_responses if r.status_code == 200
)
assert successful_logins >= 1, "至少应支持一次登录"
async def test_logout_security(self, authenticated_client):
"""
SEC-AUTH-06: 登出安全测试
验证点:
1. 登出后Token失效
2. 无法重复使用登出Token
"""
auth_api = AuthAPI(authenticated_client)
user_api = UserAPI(authenticated_client)
login_response = await auth_api.login("admin", "admin123")
token = login_response.json().get("token")
logout_response = await auth_api.logout()
if logout_response.status_code == 200:
client_with_old_token = authenticated_client.__class__(
base_url=settings.API_BASE_URL,
headers={"Authorization": f"Bearer {token}"}
)
user_api_old = UserAPI(client_with_old_token)
response = await user_api_old.get_users_by_page()
assert response.status_code in [401, 403], \
"登出后Token应失效"
async def test_password_change_security(self, authenticated_client):
"""
SEC-AUTH-07: 密码修改安全
验证点:
1. 需要旧密码验证
2. 新密码强度验证
3. 修改后需重新登录
"""
user_api = UserAPI(authenticated_client)
auth_api = AuthAPI(authenticated_client)
user_data = {
"username": "pwd_change_test",
"password": "OldPassword123!@#",
"email": "pwd_change@test.com",
"phone": "13800138000",
"status": 1
}
create_response = await user_api.create_user(user_data)
if create_response.status_code in [201, 200]:
user_id = create_response.json().get("id")
login_response = await auth_api.login(
user_data["username"],
user_data["password"]
)
assert login_response.status_code == 200
await user_api.delete_user(user_id)
async def test_account_lockout_mechanism(self, authenticated_client):
"""
SEC-AUTH-08: 账户锁定机制
验证点:
1. 多次失败后账户锁定
2. 锁定时间合理
3. 管理员可解锁
"""
auth_api = AuthAPI(authenticated_client)
for i in range(5):
response = await auth_api.login("admin", "wrong_password")
if response.status_code == 423:
assert True, "账户锁定机制生效"
return
pytest.skip("系统未实现账户锁定机制")
async def test_login_csrf_protection(self, authenticated_client):
"""
SEC-AUTH-09: 登录CSRF防护
验证点:
1. 登录表单有CSRF Token
2. CSRF Token验证
"""
auth_api = AuthAPI(authenticated_client)
login_response = await auth_api.login("admin", "admin123")
assert login_response.status_code == 200
async def test_password_reset_security(self, authenticated_client):
"""
SEC-AUTH-10: 密码重置安全
验证点:
1. 需要邮箱验证
2. 重置链接有时效
3. 重置链接一次性使用
"""
pytest.skip("密码重置功能待实现或测试")