← Назад к вопросам

Что такое сессия?

1.8 Middle🔥 181 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сессия (Session)

Сессия — это механизм для сохранения состояния пользователя между HTTP запросами, так как HTTP сам по себе является stateless протоколом. Каждый запрос независим, поэтому веб-приложения используют сессии для отслеживания пользователя, его действий и данных во время его взаимодействия с приложением.

Проблема, которую решают сессии

HTTP не имеет встроенного механизма для отслеживания пользователя между запросами:

Запрос 1: Пользователь логинится -> Сервер получает credentials
Запрос 2: Пользователь открывает профиль -> Сервер НЕ ЗНАЕТ, кто это!
Запрос 3: Пользователь покупает товар -> Сервер снова НЕ ЗНАЕТ, кто это!

Сессии решают эту проблему, сохраняя информацию о пользователе на сервере.

Как работает сессия

1. Клиент отправляет запрос (логин)
2. Сервер создаёт сессию и сохраняет данные (user_id, права доступа)
3. Сервер отправляет клиенту Session ID (обычно в cookies)
4. Клиент автоматически отправляет Session ID в каждом следующем запросе
5. Сервер по Session ID находит данные сессии
6. Сервер обрабатывает запрос с известным user_id

Пример с Flask

from flask import Flask, session, request, redirect, url_for
from werkzeug.security import check_password_hash
import secrets

app = Flask(__name__)
app.secret_key = secrets.token_hex(16)  # Секретный ключ для подписи session

# Хранилище данных сессий (в реальном приложении — Redis/Memcached)
sessions_storage = {}  # {session_id: {'user_id': 123, 'username': 'john'}}

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']
    
    # Проверяем credentials
    user = verify_user(username, password)  # Ищем в БД
    
    if user:
        # Создаём сессию
        session_id = secrets.token_hex(32)
        sessions_storage[session_id] = {
            'user_id': user['id'],
            'username': user['username'],
            'login_time': datetime.now()
        }
        
        # Отправляем Session ID в cookies
        response = redirect(url_for('profile'))
        response.set_cookie('session_id', session_id, httponly=True, secure=True)
        return response
    
    return 'Login failed', 401

@app.route('/profile')
def profile():
    # Получаем Session ID из cookies
    session_id = request.cookies.get('session_id')
    
    if not session_id or session_id not in sessions_storage:
        return redirect(url_for('login'))
    
    # Получаем данные сессии
    user_session = sessions_storage[session_id]
    user_id = user_session['user_id']
    
    # Возвращаем профиль пользователя
    user = get_user(user_id)
    return f'Welcome, {user["username"]}!'

@app.route('/logout')
def logout():
    session_id = request.cookies.get('session_id')
    if session_id in sessions_storage:
        del sessions_storage[session_id]  # Удаляем сессию
    
    response = redirect(url_for('login'))
    response.delete_cookie('session_id')
    return response

Встроенная сессия Flask

from flask import Flask, session
import secrets

app = Flask(__name__)
app.secret_key = secrets.token_hex(16)  # Ключ для подписи cookies

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    
    # Flask автоматически создаёт и подписывает session cookie
    session['user_id'] = 123
    session['username'] = username
    session.permanent = True  # Сессия будет сохранена в cookies
    
    return 'Logged in'

@app.route('/profile')
def profile():
    # Данные сессии доступны автоматически
    if 'user_id' not in session:
        return redirect(url_for('login'))
    
    user_id = session['user_id']
    return f'User ID: {user_id}'

Сессия в Django

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        
        # Аутентификация
        user = authenticate(request, username=username, password=password)
        
        if user:
            # Django создаёт сессию автоматически
            login(request, user)
            request.session['extra_data'] = 'some value'  # Можем добавлять свои данные
            return redirect('profile')
    
    return render(request, 'login.html')

@login_required  # Проверяет, есть ли сессия
def profile_view(request):
    user = request.user  # Автоматически из сессии
    extra_data = request.session.get('extra_data')
    return render(request, 'profile.html', {'user': user})

def logout_view(request):
    logout(request)  # Django удаляет сессию
    return redirect('login')

Где хранятся данные сессии

1. В памяти сервера (простой вариант, но не масштабируется):

# Хранилище в памяти приложения
sessions_memory = {}  # Теряется при перезагрузке сервера

sessions_memory['abc-123'] = {
    'user_id': 456,
    'login_time': datetime.now(),
    'cart': [1, 2, 3]
}

2. В базе данных (надёжно, но медленнее):

# PostgreSQL таблица для сессий
CREATE TABLE django_session (
    session_key VARCHAR(40) PRIMARY KEY,
    session_data TEXT,
    expire_date TIMESTAMP
);

3. В Redis (быстро и надёжно — best practice):

import redis

redis_client = redis.Redis(host='localhost', port=6379)

# Сохранить сессию
session_data = json.dumps({
    'user_id': 123,
    'username': 'john',
    'permissions': ['read', 'write']
})

# Ключ: session:{session_id}
redis_client.setex(
    f'session:{session_id}',
    3600,  # Expiration: 1 час
    session_data
)

# Получить сессию
session_data = redis_client.get(f'session:{session_id}')
if session_data:
    user_session = json.loads(session_data)
    print(f'User: {user_session["username"]}')

Жизненный цикл сессии

Рождение:
Пользователь логинится -> Сервер создаёт session_id -> Отправляет в cookies
↓
Жизнь:
Каждый запрос включает session_id -> Сервер обновляет "последний доступ" -> Сессия活
↓
Смерть:
1. Пользователь логируется (явный logout) -> Сессия удаляется
2. Timeout: пользователь неактивен 30 мин -> Сессия удаляется
3. Перезагрузка сервера -> Сессии в памяти теряются

Безопасность сессий

1. Session Fixation (атака фиксации сессии):

# ПЛОХО: использует один session_id всегда
response.set_cookie('session_id', 'fixed-id-123')

# ХОРОШО: генерируем новый session_id при логине
old_session_id = request.cookies.get('session_id')
if old_session_id in sessions:
    del sessions[old_session_id]  # Удаляем старую

new_session_id = secrets.token_hex(32)  # Новый ID
sessions[new_session_id] = user_data
response.set_cookie('session_id', new_session_id)

2. Защита от CSRF (Cross-Site Request Forgery):

# Django автоматически включает CSRF protection
<form method="POST">
    {% csrf_token %}  <!-- Скрытый токен из сессии -->
    <input name="username">
    <button>Отправить</button>
</form>

3. HTTPOnly флаг (предотвращает доступ из JavaScript):

# Правильно: session_id недоступна для JavaScript
response.set_cookie(
    'session_id',
    session_id,
    httponly=True,  # Можно отправить только HTTP запросом
    secure=True,    # Только HTTPS
    samesite='Strict'  # Не отправлять при cross-site запросах
)

Практический пример: Корзина покупок

from flask import Flask, session, request

app = Flask(__name__)
app.secret_key = 'secret'

@app.route('/add-to-cart/<int:product_id>')
def add_to_cart(product_id):
    # Инициализируем корзину в сессии
    if 'cart' not in session:
        session['cart'] = []
    
    # Добавляем товар
    session['cart'].append(product_id)
    session.modified = True  # Помечаем сессию как изменённую
    
    return f'Added product {product_id} to cart'

@app.route('/view-cart')
def view_cart():
    # Корзина из сессии доступна во всех запросах
    cart = session.get('cart', [])
    total = sum(get_price(pid) for pid in cart)
    
    return f'Cart: {cart}, Total: ${total}'

@app.route('/checkout')
def checkout():
    # Сессия содержит данные пользователя и корзину
    user_id = session['user_id']
    cart = session['cart']
    
    # Создаём заказ
    order = create_order(user_id, cart)
    
    # Очищаем корзину
    session['cart'] = []
    session.modified = True
    
    return f'Order created: {order["id"]}'

Вывод

Сессия — это критически важный механизм веб-приложений, позволяющий:

  • Отслеживать пользователей между stateless HTTP запросами
  • Сохранять состояние (user_id, корзину, предпочтения)
  • Реализовать аутентификацию и авторизацию
  • Поддерживать пользовательский контекст

Данные сессии обычно хранятся в Redis для масштабируемости, защищаются HTTPOnly cookies и CSRF токенами, и автоматически удаляются по timeout.

Что такое сессия? | PrepBro