init_guac

This commit is contained in:
root
2025-11-25 09:58:37 +03:00
parent 68c8f0e80d
commit 9d5bdd57a7
57 changed files with 18272 additions and 0 deletions

View File

@ -0,0 +1,230 @@
# 🔧 Token Issue Fix - Восстановление подключений
## Проблема
При восстановлении подключений после logout/login возникала ошибка 403 Forbidden при переключении между подключениями.
### Причина
Middleware получал Guacamole токен **напрямую из JWT payload**, а не из активной сессии в Redis.
**ДО исправления:**
```python
# middleware.py (строка 77)
user_token = jwt_payload.get("guac_token") # ❌ guac_token нет в JWT!
```
**Проблема:**
- JWT содержит только `session_id`, а не `guac_token`
- При логине создается новая сессия в Redis с новым Guacamole токеном
- Но middleware не загружал сессию из Redis, поэтому `user_token` был `None` или старый
---
## Решение
### ✅ Исправление в `middleware.py`
Теперь middleware:
1. Извлекает `session_id` из JWT
2. Загружает актуальную сессию из Redis
3. Получает текущий Guacamole токен из сессии
**ПОСЛЕ исправления:**
```python
# middleware.py (строки 77-112)
session_id = jwt_payload.get("session_id")
if session_id:
# Загружаем сессию из Redis
from auth.session_storage import session_storage
session_data = session_storage.get_session(session_id)
if session_data:
# ✅ Получаем актуальный Guacamole token из сессии
user_token = session_data.get("guac_token")
else:
# Сессия истекла или удалена
user_token = None
else:
# Backwards compatibility
user_token = jwt_payload.get("guac_token")
```
---
## Как это работает
### Схема аутентификации
```
┌─────────────────┐
│ 1. Пользователь │
│ логинится │
└────────┬────────┘
┌────────────────────────────────────────────┐
│ 2. Guacamole возвращает auth_token │
└────────┬───────────────────────────────────┘
┌────────────────────────────────────────────┐
│ 3. API создает Redis сессию: │
│ - session_id: "abc123" │
│ - guac_token: "guac_token_xyz" │
│ - user_info: {...} │
└────────┬───────────────────────────────────┘
┌────────────────────────────────────────────┐
│ 4. API создает JWT token: │
│ { │
│ "username": "user", │
│ "role": "USER", │
│ "session_id": "abc123", ← ТОЛЬКО ID! │
│ "exp": ... │
│ } │
└────────┬───────────────────────────────────┘
┌────────────────────────────────────────────┐
│ 5. Клиент отправляет запросы с JWT │
└────────┬───────────────────────────────────┘
┌────────────────────────────────────────────┐
│ 6. Middleware: │
│ - Извлекает session_id из JWT │
│ - Загружает сессию из Redis ✅ │
│ - Получает актуальный guac_token ✅ │
└────────────────────────────────────────────┘
```
### Восстановление подключений
```
User API Redis Guacamole
│ │ │ │
│─────LOGIN──────>│ │ │
│ │───AUTH───────────────────────────────>│
│ │<──guac_token_A────────────────────────│
│ │ │ │
│ │──CREATE SESSION──>│ │
│ │ (guac_token_A) │ │
│<─JWT(session_id)│ │ │
│ │ │ │
│──CREATE CONN───>│ │ │
│ │──GET TOKEN───────>│ │
│ │<─guac_token_A─────│ │
│ │────CREATE CONNECTION─────────────────>│
│<─connection_url─│ │ │
│ (token_A) │ │ │
│ │ │ │
│────LOGOUT──────>│ │ │
│ │──DELETE SESSION──>│ │
│ │ │ │
│─────LOGIN──────>│ │ │
│ │───AUTH───────────────────────────────>│
│ │<──guac_token_B────────────────────────│ ← NEW TOKEN!
│ │ │ │
│ │──CREATE SESSION──>│ │
│ │ (guac_token_B) │ │
│<─JWT(session_id)│ │ │
│ │ │ │
│──GET CONNECTIONS│ │ │
│ │──GET TOKEN───────>│ │
│ │<─guac_token_B─────│ ✅ CURRENT TOKEN │
│<─URLs (token_B) │ │ │
│ ✅ РАБОТАЕТ! │ │ │
```
---
## Применение исправления
```bash
cd GuacamoleRemoteAccess
docker-compose restart api
```
---
## Проверка
После применения исправления:
1. ✅ Логинитесь в клиент
2. ✅ Создайте подключение к любой машине
3. ✅ Сделайте logout
4. ✅ Залогиньтесь снова
5. ✅ Восстановите подключение
6. ✅ Создайте новое подключение к другой машине
7. ✅ Переключайтесь между подключениями → **403 ошибки больше нет!** 🎉
---
## Технические детали
### JWT Payload (после логина)
```json
{
"username": "user",
"role": "USER",
"permissions": [],
"session_id": "4edb****************************8c45",
"token_type": "access",
"exp": 1730721881,
"iat": 1730718281,
"iss": "remote-access-api"
}
```
**Замечание:** `guac_token` НЕ хранится в JWT по соображениям безопасности.
### Redis Session (при логине)
```json
{
"user_info": {
"username": "user",
"role": "USER",
"permissions": []
},
"guac_token": "589f****************************6edc",
"ecdh_session_id": "abc123...",
"created_at": "2025-11-04T14:24:41.123456Z",
"expires_at": "2025-11-04T15:24:41.123456Z"
}
```
---
## Backwards Compatibility
Исправление поддерживает старые JWT токены (если они содержат `guac_token` напрямую):
```python
else:
# Старый формат JWT с guac_token напрямую (backwards compatibility)
user_token = jwt_payload.get("guac_token")
```
Это позволяет избежать проблем при rolling deployment.
---
## Связанные файлы
- `GuacamoleRemoteAccess/api/auth/middleware.py` - middleware для извлечения токена
- `GuacamoleRemoteAccess/api/auth/utils.py` - создание JWT с `session_id`
- `GuacamoleRemoteAccess/api/auth/guacamole_auth.py` - создание сессий в Redis
- `GuacamoleRemoteAccess/api/auth/session_storage.py` - хранилище сессий
- `GuacamoleRemoteAccess/api/main.py` - endpoint `/connections` для восстановления
---
## Дата исправления
2025-11-04