WIP-CHECKPOINT[auth-refactor]: 固化工程师崩溃前部分成果 + 同树其他未提交WIP(仅源码,不含密钥/二进制)-- 待重激活工程师续作
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 环境门禁(三端认证重构 AUTH-01)
|
||||
# =============================================================================
|
||||
# 说明:根据 app_env 判断当前是否生产环境,统一控制以下强校验的启用:
|
||||
# 1. 企微 WebView(wxwork)UA 校验
|
||||
# 2. 管理后台 IP 白名单
|
||||
# 3. 真实企微 OAuth2 静默授权
|
||||
#
|
||||
# 设计原则(决策来源:system_design.md 环境门禁矩阵):
|
||||
# - 仅 production 环境启用上述强校验
|
||||
# - dev / test / 未配置 一律视为非生产,跳过强校验,方便本地开发
|
||||
#
|
||||
# 使用方式:
|
||||
# from app.utils.env_gating import is_production, ip_in_whitelist
|
||||
# if is_production():
|
||||
# ...
|
||||
# =============================================================================
|
||||
|
||||
from ipaddress import ip_address, ip_network
|
||||
from typing import List, Optional
|
||||
|
||||
from app.config import settings
|
||||
|
||||
|
||||
def is_production() -> bool:
|
||||
"""判断是否生产环境。
|
||||
|
||||
仅当 app_env == "production" 时返回 True。
|
||||
其他值(dev / test / 空字符串)一律视为非生产环境,
|
||||
从而跳过 UA 校验 / IP 白名单 / 真实 OAuth 等强校验。
|
||||
|
||||
Returns:
|
||||
bool: True=生产环境,False=非生产环境
|
||||
"""
|
||||
return (settings.app_env or "dev").strip().lower() == "production"
|
||||
|
||||
|
||||
def _parse_allowed_ips(raw: Optional[str]) -> List[str]:
|
||||
"""把逗号分隔的 IP / 网段字符串解析为去空白后的列表。
|
||||
|
||||
Args:
|
||||
raw: 形如 "117.147.35.138,218.75.34.87,10.240.0.0/16" 的字符串
|
||||
|
||||
Returns:
|
||||
List[str]: 非空条目列表(已去除首尾空白)
|
||||
"""
|
||||
if not raw:
|
||||
return []
|
||||
return [item.strip() for item in raw.split(",") if item.strip()]
|
||||
|
||||
|
||||
def ip_in_whitelist(client_ip: str, allowed: Optional[str] = None) -> bool:
|
||||
"""判断客户端 IP 是否在白名单内(支持 CIDR 网段)。
|
||||
|
||||
匹配规则:
|
||||
- 白名单为空 → 保守拒绝(不开放)
|
||||
- client_ip 格式非法 → 拒绝
|
||||
- 白名单条目含 "/" → 按 CIDR 网段匹配(ip_network, strict=False)
|
||||
- 白名单条目为单 IP → 精确相等匹配
|
||||
|
||||
Args:
|
||||
client_ip: 客户端 IP(如 "10.240.1.5")
|
||||
allowed: 白名单字符串(逗号分隔,支持 CIDR)。
|
||||
缺省时读取 settings.admin_allowed_ips。
|
||||
|
||||
Returns:
|
||||
bool: True=在白名单内,False=不在 / 格式非法 / 白名单为空
|
||||
"""
|
||||
if not client_ip:
|
||||
return False
|
||||
|
||||
allowed_raw = allowed if allowed is not None else settings.admin_allowed_ips
|
||||
entries = _parse_allowed_ips(allowed_raw)
|
||||
if not entries:
|
||||
# 白名单为空 → 保守策略:不开放任何 IP
|
||||
return False
|
||||
|
||||
try:
|
||||
client = ip_address(client_ip)
|
||||
except ValueError:
|
||||
# 客户端 IP 格式非法 → 拒绝
|
||||
return False
|
||||
|
||||
for entry in entries:
|
||||
try:
|
||||
if "/" in entry:
|
||||
# CIDR 网段匹配(如 10.240.0.0/16)
|
||||
network = ip_network(entry, strict=False)
|
||||
if client in network:
|
||||
return True
|
||||
else:
|
||||
# 单 IP 精确匹配
|
||||
if client == ip_address(entry):
|
||||
return True
|
||||
except ValueError:
|
||||
# 单个白名单条目格式非法 → 跳过,继续匹配其他条目
|
||||
continue
|
||||
|
||||
return False
|
||||
Reference in New Issue
Block a user