Browse Source

websocket Client

origin/hotfix/hlk-flight
root 4 months ago
parent
commit
a3b7f1c7d2
  1. 112
      WEBSOCKET_SSL_FIX.md
  2. 23
      app/core/config/settings.py
  3. 15
      app/core/websocket/client.py
  4. 64
      modify.md
  5. 2
      requirements.txt
  6. 99
      test_websocket_ssl.py

112
WEBSOCKET_SSL_FIX.md

@ -0,0 +1,112 @@
# WebSocket SSL证书验证修复说明
## 问题描述
在使用WebSocket客户端连接时,遇到SSL证书验证失败的错误:
```
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:997)
```
## 解决方案
### 1. 配置化SSL证书验证
系统现在支持通过配置来控制SSL证书验证行为,而不是硬编码跳过验证。
### 2. 环境变量配置
可以通过环境变量来控制SSL验证行为:
```bash
# 开发环境(跳过SSL验证)
export WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
export WEBSOCKET_SSL_VERIFY_HOSTNAME=false
# 生产环境(启用SSL验证)
export WEBSOCKET_SSL_VERIFY_CERTIFICATE=true
export WEBSOCKET_SSL_VERIFY_HOSTNAME=true
```
### 3. 配置文件设置
也可以在 `.env` 文件中设置:
```env
# WebSocket SSL配置
WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
WEBSOCKET_SSL_VERIFY_HOSTNAME=false
```
### 4. 默认配置
- **开发环境**:默认跳过SSL证书验证(`ssl_verify_certificate=false`)
- **生产环境**:建议启用SSL证书验证(`ssl_verify_certificate=true`)
## 使用方法
### 1. 安装依赖
确保已安装websockets依赖:
```bash
pip install websockets==12.0
```
### 2. 创建WebSocket客户端
```python
from app.core.websocket.client import WebSocketClient
# 创建客户端
client = WebSocketClient("wss://your-server.com", "my_client")
# 连接(会自动根据配置处理SSL验证)
success = await client.connect()
```
### 3. 测试验证
运行测试脚本验证修复效果:
```bash
python test_websocket_ssl.py
```
## 安全注意事项
1. **开发环境**:可以安全地跳过SSL证书验证
2. **生产环境**:强烈建议启用SSL证书验证,使用有效的SSL证书
3. **自签名证书**:如果使用自签名证书,需要将证书添加到信任链中
## 相关文件
- `app/core/websocket/client.py` - WebSocket客户端实现
- `app/core/config/settings.py` - 配置管理
- `test_websocket_ssl.py` - 测试脚本
- `requirements.txt` - 依赖管理
## 故障排除
### 1. 仍然出现SSL错误
检查配置是否正确设置:
```python
from app.core.config.settings import config
print(f"SSL验证配置: {config.websocket.ssl_verify_certificate}")
```
### 2. 生产环境需要跳过验证
如果生产环境必须跳过SSL验证,可以设置环境变量:
```bash
export WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
```
### 3. 使用自签名证书
如果使用自签名证书,建议:
1. 将证书添加到系统信任链
2. 或者使用配置跳过验证(仅限开发环境)

23
app/core/config/settings.py

@ -31,6 +31,26 @@ class AdbConfig(BaseSettings):
env_file = ".env"
class WebSocketConfig(BaseSettings):
"""WebSocket配置类"""
# SSL配置
ssl_verify_certificate: bool = False # 是否验证SSL证书(开发环境建议设为False)
ssl_verify_hostname: bool = False # 是否验证主机名(开发环境建议设为False)
# 连接配置
connection_timeout: int = 30
reconnect_attempts: int = 5
reconnect_delay: float = 1.0
# 心跳配置
heartbeat_interval: int = 30
class Config:
env_prefix = "WEBSOCKET_"
env_file = ".env"
class AppConfig(BaseSettings):
"""应用配置类"""
@ -57,6 +77,9 @@ class AppConfig(BaseSettings):
# ADB配置
adb: AdbConfig = AdbConfig()
# WebSocket配置
websocket: WebSocketConfig = WebSocketConfig()
class Config:
env_prefix = "APP_"
env_file = ".env"

15
app/core/websocket/client.py

@ -62,7 +62,20 @@ class WebSocketClient:
logger.info(f"WebSocket客户端 {self.name} 正在连接...")
# 建立WebSocket连接
self._websocket = await websockets.connect(self.url)
# 根据配置决定是否跳过SSL证书验证
ssl_context = None
if self.url.startswith('wss://'):
from app.core.config.settings import config
import ssl
ssl_context = ssl.create_default_context()
# 根据配置决定是否验证证书和主机名
if not config.websocket.ssl_verify_certificate:
ssl_context.verify_mode = ssl.CERT_NONE
if not config.websocket.ssl_verify_hostname:
ssl_context.check_hostname = False
self._websocket = await websockets.connect(self.url, ssl=ssl_context)
self._state = WebSocketClientState.CONNECTED
self._reconnect_attempts = 0

64
modify.md

@ -1,5 +1,69 @@
# 修改记录
## 2025-08-11
### WebSocket SSL证书验证问题修复
**问题**:WebSocket客户端连接时出现SSL证书验证失败错误
```
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:997)
```
**解决方案**:在WebSocket客户端连接时跳过SSL证书验证(仅用于开发测试)
**文件变更**:
- 更新 `app/core/websocket/client.py` - 在connect方法中添加SSL证书验证跳过逻辑
**修改内容**:
```python
# 建立WebSocket连接
# 根据配置决定是否跳过SSL证书验证
ssl_context = None
if self.url.startswith('wss://'):
from app.core.config.settings import config
import ssl
ssl_context = ssl.create_default_context()
# 根据配置决定是否验证证书和主机名
if not config.websocket.ssl_verify_certificate:
ssl_context.verify_mode = ssl.CERT_NONE
if not config.websocket.ssl_verify_hostname:
ssl_context.check_hostname = False
self._websocket = await websockets.connect(self.url, ssl=ssl_context)
```
**配置化设计**:
- 在 `app/core/config/settings.py` 中添加 `WebSocketConfig`
- 支持通过环境变量或配置文件控制SSL验证行为
- 默认开发环境跳过证书验证,生产环境可通过配置启用
**环境变量配置**:
```bash
# 开发环境(跳过SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=false
WEBSOCKET_SSL_VERIFY_HOSTNAME=false
# 生产环境(启用SSL验证)
WEBSOCKET_SSL_VERIFY_CERTIFICATE=true
WEBSOCKET_SSL_VERIFY_HOSTNAME=true
```
**注意事项**:
- 开发环境默认跳过SSL证书验证
- 生产环境建议启用SSL证书验证
- 可通过环境变量灵活配置
**相关修改**:
- 启用 `requirements.txt` 中的 `websockets==12.0` 依赖
- 添加 `WebSocketConfig` 配置类到 `app/core/config/settings.py`
- 创建 `test_websocket_ssl.py` 测试脚本验证修复效果
**测试验证**:
运行测试脚本验证修复效果:
```bash
python test_websocket_ssl.py
```
## 2025-08-07
### 日志系统简化优化

2
requirements.txt

@ -21,7 +21,7 @@ paramiko==3.3.1
python-multipart==0.0.6
# 可选依赖(根据实际需要启用)
# websockets==12.0 # WebSocket支持
websockets==12.0 # WebSocket支持
# httpx==0.25.2 # HTTP客户端
# aiofiles==23.2.1 # 异步文件操作
# watchdog==3.0.0 # 文件监控

99
test_websocket_ssl.py

@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""
WebSocket SSL证书验证测试脚本
"""
import asyncio
import sys
import os
# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from app.core.websocket.client import WebSocketClient
from app.core.config.settings import config
from app.utils.log import get_logger
logger = get_logger(__name__)
async def test_websocket_ssl():
"""测试WebSocket SSL连接"""
print("=== WebSocket SSL证书验证测试 ===")
# 显示当前配置
print(f"SSL证书验证: {config.websocket.ssl_verify_certificate}")
print(f"SSL主机名验证: {config.websocket.ssl_verify_hostname}")
# 测试URL(使用自签名证书的WebSocket服务器)
test_url = "wss://echo.websocket.org" # 使用公共测试服务器
print(f"\n测试连接到: {test_url}")
try:
# 创建WebSocket客户端
client = WebSocketClient(test_url, "test_client")
# 尝试连接
print("正在连接...")
success = await client.connect()
if success:
print("✅ 连接成功!SSL证书验证问题已修复")
# 发送测试消息
test_message = {
"type": "test",
"data": "Hello WebSocket!"
}
# 注册消息处理器
def handle_response(message):
print(f"收到响应: {message}")
client.register_message_handler("test", handle_response)
# 等待一段时间接收响应
await asyncio.sleep(2)
# 断开连接
await client.disconnect()
print("连接已断开")
else:
print("❌ 连接失败")
except Exception as e:
print(f"❌ 测试过程中出现异常: {e}")
logger.error(f"WebSocket SSL测试失败: {e}")
async def test_config_override():
"""测试配置覆盖功能"""
print("\n=== 配置覆盖测试 ===")
# 临时修改配置
original_verify_cert = config.websocket.ssl_verify_certificate
original_verify_host = config.websocket.ssl_verify_hostname
try:
# 设置为启用验证(应该会失败)
config.websocket.ssl_verify_certificate = True
config.websocket.ssl_verify_hostname = True
print("配置已设置为启用SSL验证")
print(f"SSL证书验证: {config.websocket.ssl_verify_certificate}")
print(f"SSL主机名验证: {config.websocket.ssl_verify_hostname}")
# 这里可以添加更多测试逻辑
finally:
# 恢复原始配置
config.websocket.ssl_verify_certificate = original_verify_cert
config.websocket.ssl_verify_hostname = original_verify_host
print("配置已恢复")
if __name__ == "__main__":
print("开始WebSocket SSL测试...")
# 运行测试
asyncio.run(test_websocket_ssl())
asyncio.run(test_config_override())
print("\n测试完成!")
Loading…
Cancel
Save