init_guac
This commit is contained in:
230
guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md
Executable file
230
guacamole_test_11_26/docs/TOKEN_FIX_SUMMARY.md
Executable 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
|
||||
|
||||
Reference in New Issue
Block a user