Files
novalon-manage-system/test-suite/tests/security/test_permission_boundary.py
T
张翔 1e3dc11d59 refactor(test): 重构测试套件结构并优化测试配置
feat(test-suite): 新增测试套件模块,包含API测试客户端和测试配置
fix(api): 修复数据库实体和仓库的删除操作返回值
style(api): 统一数据库表名和字段命名
perf(api): 添加缓存注解提升配置查询性能
test(api): 添加H2测试数据库配置支持
chore: 清理旧的测试文件和脚本
2026-04-01 20:57:24 +08:00

276 lines
8.7 KiB
Python

"""
权限边界测试套件
测试范围:
1. 角色权限边界测试
2. 数据访问权限测试
3. 操作权限测试
4. 菜单权限测试
5. API权限测试
作者: 张翔
日期: 2026-04-01
"""
import pytest
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from api.role_api import RoleAPI
from api.menu_api import MenuAPI
from config.settings import settings
@pytest.mark.security
@pytest.mark.asyncio
class TestPermissionBoundary:
"""权限边界测试类"""
async def test_role_based_access_control(self, authenticated_client):
"""
SEC-PERM-01: 基于角色的访问控制
验证点:
1. 不同角色有不同权限
2. 权限正确分配
3. 权限正确验证
"""
role_api = RoleAPI(authenticated_client)
roles_response = await role_api.get_roles_by_page()
assert roles_response.status_code == 200
roles = roles_response.json().get("content", [])
assert len(roles) > 0, "应至少有一个角色"
for role in roles:
assert "roleName" in role, "角色应包含名称"
assert "roleKey" in role, "角色应包含标识"
async def test_user_data_isolation(self, authenticated_client):
"""
SEC-PERM-02: 用户数据隔离
验证点:
1. 用户只能访问自己的数据
2. 无法访问其他用户敏感信息
3. 管理员可访问所有数据
"""
user_api = UserAPI(authenticated_client)
users_response = await user_api.get_users_by_page()
assert users_response.status_code == 200
users = users_response.json().get("content", [])
for user in users:
if "password" in user:
assert user["password"] != "admin123", \
"密码不应明文返回"
assert not user["password"].startswith("$2"), \
"密码哈希不应返回给前端"
async def test_cross_user_access_prevention(self, authenticated_client):
"""
SEC-PERM-03: 跨用户访问防护
验证点:
1. 普通用户无法修改其他用户数据
2. 用户ID绑定验证
"""
user_api = UserAPI(authenticated_client)
users_response = await user_api.get_users_by_page()
users = users_response.json().get("content", [])
if len(users) > 1:
other_user = next(
(u for u in users if u.get("username") != "admin"),
None
)
if other_user:
response = await user_api.get_user_by_id(other_user["id"])
assert response.status_code in [200, 403], \
"应正确处理跨用户访问"
async def test_menu_permission_control(self, authenticated_client):
"""
SEC-PERM-04: 菜单权限控制
验证点:
1. 不同角色看到不同菜单
2. 菜单权限标识验证
3. 无权限菜单隐藏
"""
menu_api = MenuAPI(authenticated_client)
menus_response = await menu_api.get_menus()
assert menus_response.status_code == 200
menus = menus_response.json() if isinstance(
menus_response.json(), list
) else menus_response.json().get("data", [])
for menu in menus:
assert "menuName" in menu or "name" in menu, \
"菜单应包含名称"
async def test_api_permission_validation(self, authenticated_client):
"""
SEC-PERM-05: API权限验证
验证点:
1. 每个API有权限控制
2. 无权限返回403
3. 未认证返回401
"""
user_api = UserAPI(authenticated_client)
client_without_auth = authenticated_client.__class__(
base_url=settings.API_BASE_URL
)
user_api_no_auth = UserAPI(client_without_auth)
response = await user_api_no_auth.get_users_by_page()
assert response.status_code in [401, 403], \
"未认证请求应被拒绝"
async def test_privilege_escalation_prevention(self, authenticated_client):
"""
SEC-PERM-06: 权限提升防护
验证点:
1. 用户无法自我提升权限
2. 角色修改需管理员权限
"""
user_api = UserAPI(authenticated_client)
role_api = RoleAPI(authenticated_client)
users_response = await user_api.get_users_by_page()
users = users_response.json().get("content", [])
current_user = next(
(u for u in users if u.get("username") == "admin"),
None
)
if current_user:
roles_response = await role_api.get_roles_by_page()
roles = roles_response.json().get("content", [])
admin_role = next(
(r for r in roles if "admin" in r.get("roleKey", "").lower()),
None
)
assert admin_role is not None, "应存在管理员角色"
async def test_operation_permission_check(self, authenticated_client):
"""
SEC-PERM-07: 操作权限检查
验证点:
1. 创建操作需权限
2. 修改操作需权限
3. 删除操作需权限
"""
user_api = UserAPI(authenticated_client)
test_user_data = {
"username": "perm_test_user",
"password": "Test123!@#",
"email": "perm_test@test.com",
"phone": "13800138000",
"status": 1
}
create_response = await user_api.create_user(test_user_data)
if create_response.status_code in [201, 200]:
user_id = create_response.json().get("id")
update_response = await user_api.update_user(
user_id,
{"email": "updated@test.com"}
)
assert update_response.status_code in [200, 403]
delete_response = await user_api.delete_user(user_id)
assert delete_response.status_code in [200, 204, 403]
async def test_data_filter_by_permission(self, authenticated_client):
"""
SEC-PERM-08: 数据权限过滤
验证点:
1. 查询结果按权限过滤
2. 敏感字段脱敏
"""
user_api = UserAPI(authenticated_client)
users_response = await user_api.get_users_by_page()
if users_response.status_code == 200:
users = users_response.json().get("content", [])
for user in users:
assert "password" not in user or \
user.get("password") == "******", \
"密码字段应脱敏或不返回"
async def test_role_permission_inheritance(self, authenticated_client):
"""
SEC-PERM-09: 角色权限继承
验证点:
1. 角色权限可继承
2. 子角色权限不超过父角色
"""
role_api = RoleAPI(authenticated_client)
roles_response = await role_api.get_roles_by_page()
if roles_response.status_code == 200:
roles = roles_response.json().get("content", [])
for role in roles:
if "parentId" in role and role["parentId"]:
parent_role = next(
(r for r in roles if r.get("id") == role["parentId"]),
None
)
async def test_admin_privilege_boundary(self, authenticated_client):
"""
SEC-PERM-10: 管理员权限边界
验证点:
1. 超级管理员有所有权限
2. 普通管理员权限受限
3. 管理员操作审计
"""
user_api = UserAPI(authenticated_client)
role_api = RoleAPI(authenticated_client)
users_response = await user_api.get_users_by_page()
assert users_response.status_code == 200
roles_response = await role_api.get_roles_by_page()
assert roles_response.status_code == 200
users = users_response.json().get("content", [])
roles = roles_response.json().get("content", [])
admin_user = next(
(u for u in users if u.get("username") == "admin"),
None
)
if admin_user:
assert admin_user.get("status") == 1, \
"管理员账户应处于激活状态"