Files
zcglxt/tests/api/test_auth.py
Claude e71181f0a3 fix: 修复多个关键问题
- 修复前端路由守卫:未登录时不显示提示,直接跳转登录页
- 修复API拦截器:401错误不显示提示,直接跳转
- 增强验证码显示:图片尺寸从120x40增加到200x80
- 增大验证码字体:从28号增加到48号
- 优化验证码字符:排除易混淆的0和1
- 减少干扰线:从5条减少到3条,添加背景色优化
- 增强登录API日志:添加详细的调试日志
- 增强验证码生成和验证日志
- 优化异常处理和错误追踪

影响文件:
- src/router/index.ts
- src/api/request.ts
- app/services/auth_service.py
- app/api/v1/auth.py
- app/schemas/user.py

测试状态:
- 前端构建通过
- 后端语法检查通过
- 验证码显示效果优化完成

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 00:26:21 +08:00

357 lines
12 KiB
Python

"""
认证模块API测试
测试内容:
- 用户登录
- Token刷新
- 用户登出
- 修改密码
- 验证码获取
"""
import pytest
# from fastapi.testclient import TestClient
# from app.core.config import settings
# class TestAuthLogin:
# """测试用户登录"""
#
# def test_login_success(self, client: TestClient, test_user):
# """测试登录成功"""
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "testuser",
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 200
# data = response.json()
# assert data["code"] == 200
# assert "access_token" in data["data"]
# assert "refresh_token" in data["data"]
# assert data["data"]["token_type"] == "Bearer"
# assert "user" in data["data"]
#
# def test_login_wrong_password(self, client: TestClient):
# """测试密码错误"""
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "testuser",
# "password": "WrongPassword",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 401
# data = response.json()
# assert data["code"] == 10001 # 用户名或密码错误
#
# def test_login_user_not_found(self, client: TestClient):
# """测试用户不存在"""
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "nonexistent",
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 401
#
# def test_login_missing_fields(self, client: TestClient):
# """测试缺少必填字段"""
# response = client.post(
# "/api/v1/auth/login",
# json={"username": "testuser"}
# )
# assert response.status_code == 422 # Validation error
#
# @pytest.mark.parametrize("username", [
# "", # 空字符串
# "ab", # 太短
# "a" * 51, # 太长
# ])
# def test_login_invalid_username(self, client: TestClient, username):
# """测试无效用户名"""
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": username,
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 422
#
# @pytest.mark.parametrize("password", [
# "", # 空字符串
# "short", # 太短
# "nospecial123", # 缺少特殊字符
# "NOlower123!", # 缺少小写字母
# "noupper123!", # 缺少大写字母
# "NoNumber!!", # 缺少数字
# ])
# def test_login_invalid_password(self, client: TestClient, password):
# """测试无效密码"""
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "testuser",
# "password": password,
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# # 某些情况可能是422(验证失败),某些情况可能是401(认证失败)
# assert response.status_code in [400, 422, 401]
#
# def test_login_account_locked(self, client: TestClient, db):
# """测试账户被锁定"""
# # 创建一个锁定的账户
# # ... 创建锁定用户逻辑
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "lockeduser",
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 403
#
# def test_login_account_disabled(self, client: TestClient, db):
# """测试账户被禁用"""
# # ... 创建禁用用户逻辑
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "disableduser",
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# assert response.status_code == 403
# class TestTokenRefresh:
# """测试Token刷新"""
#
# def test_refresh_token_success(self, client: TestClient, test_user):
# """测试刷新Token成功"""
# # 先登录获取refresh_token
# login_response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "testuser",
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test-uuid"
# }
# )
# refresh_token = login_response.json()["data"]["refresh_token"]
#
# # 刷新Token
# response = client.post(
# "/api/v1/auth/refresh",
# json={"refresh_token": refresh_token}
# )
# assert response.status_code == 200
# data = response.json()
# assert data["code"] == 200
# assert "access_token" in data["data"]
# assert "expires_in" in data["data"]
#
# def test_refresh_token_invalid(self, client: TestClient):
# """测试无效的refresh_token"""
# response = client.post(
# "/api/v1/auth/refresh",
# json={"refresh_token": "invalid_token"}
# )
# assert response.status_code == 401
# data = response.json()
# assert data["code"] == 10004 # Token无效
#
# def test_refresh_token_expired(self, client: TestClient):
# """测试过期的refresh_token"""
# response = client.post(
# "/api/v1/auth/refresh",
# json={"refresh_token": "expired_token"}
# )
# assert response.status_code == 401
# data = response.json()
# assert data["code"] == 10003 # Token过期
# class TestAuthLogout:
# """测试用户登出"""
#
# def test_logout_success(self, client: TestClient, auth_headers):
# """测试登出成功"""
# response = client.post(
# "/api/v1/auth/logout",
# headers=auth_headers
# )
# assert response.status_code == 200
# data = response.json()
# assert data["code"] == 200
# assert data["message"] == "登出成功"
#
# def test_logout_without_auth(self, client: TestClient):
# """测试未认证登出"""
# response = client.post("/api/v1/auth/logout")
# assert response.status_code == 401
# class TestChangePassword:
# """测试修改密码"""
#
# def test_change_password_success(self, client: TestClient, auth_headers):
# """测试修改密码成功"""
# response = client.put(
# "/api/v1/auth/change-password",
# headers=auth_headers,
# json={
# "old_password": "Test123",
# "new_password": "NewTest456",
# "confirm_password": "NewTest456"
# }
# )
# assert response.status_code == 200
# data = response.json()
# assert data["code"] == 200
# assert data["message"] == "密码修改成功"
#
# def test_change_password_wrong_old_password(self, client: TestClient, auth_headers):
# """测试旧密码错误"""
# response = client.put(
# "/api/v1/auth/change-password",
# headers=auth_headers,
# json={
# "old_password": "WrongPassword",
# "new_password": "NewTest456",
# "confirm_password": "NewTest456"
# }
# )
# assert response.status_code == 400
#
# def test_change_password_mismatch(self, client: TestClient, auth_headers):
# """测试两次密码不一致"""
# response = client.put(
# "/api/v1/auth/change-password",
# headers=auth_headers,
# json={
# "old_password": "Test123",
# "new_password": "NewTest456",
# "confirm_password": "DifferentPass789"
# }
# )
# assert response.status_code == 400
#
# def test_change_password_weak_password(self, client: TestClient, auth_headers):
# """测试弱密码"""
# response = client.put(
# "/api/v1/auth/change-password",
# headers=auth_headers,
# json={
# "old_password": "Test123",
# "new_password": "weak",
# "confirm_password": "weak"
# }
# )
# assert response.status_code == 400
#
# def test_change_password_without_auth(self, client: TestClient):
# """测试未认证修改密码"""
# response = client.put(
# "/api/v1/auth/change-password",
# json={
# "old_password": "Test123",
# "new_password": "NewTest456",
# "confirm_password": "NewTest456"
# }
# )
# assert response.status_code == 401
# class TestCaptcha:
# """测试验证码"""
#
# def test_get_captcha_success(self, client: TestClient):
# """测试获取验证码成功"""
# response = client.get("/api/v1/auth/captcha")
# assert response.status_code == 200
# data = response.json()
# assert data["code"] == 200
# assert "captcha_key" in data["data"]
# assert "captcha_image" in data["data"]
# assert data["data"]["captcha_image"].startswith("data:image/png;base64,")
#
# @pytest.mark.parametrize("count", range(5))
# def test_get_captcha_multiple_times(self, client: TestClient, count):
# """测试多次获取验证码,每次应该不同"""
# response = client.get("/api/v1/auth/captcha")
# assert response.status_code == 200
# data = response.json()
# assert data["data"]["captcha_key"] is not None
# class TestRateLimiting:
# """测试请求频率限制"""
#
# def test_login_rate_limiting(self, client: TestClient):
# """测试登录接口频率限制"""
# # 登录接口限制10次/分钟
# for i in range(11):
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": "testuser",
# "password": "wrongpass",
# "captcha": "1234",
# "captcha_key": f"test-{i}"
# }
# )
#
# # 第11次应该被限流
# assert response.status_code == 429
# data = response.json()
# assert data["code"] == 429
# assert "retry_after" in data["data"]
# 测试SQL注入攻击
# class TestSecurity:
# """测试安全性"""
#
# def test_sql_injection_prevention(self, client: TestClient):
# """测试防止SQL注入"""
# malicious_inputs = [
# "admin' OR '1'='1",
# "admin'--",
# "admin'/*",
# "' OR 1=1--",
# "'; DROP TABLE users--"
# ]
#
# for malicious_input in malicious_inputs:
# response = client.post(
# "/api/v1/auth/login",
# json={
# "username": malicious_input,
# "password": "Test123",
# "captcha": "1234",
# "captcha_key": "test"
# }
# )
# # 应该返回认证失败,而不是数据库错误
# assert response.status_code in [401, 400, 422]