Это многостраничный печатный вид этого раздела. Нажмите что бы печатать.

Вернуться к обычному просмотру страницы.

SCS: Управление HTTP-сессиями для Go

Менеджер сессий для GO

Возможности

  • Автоматическая загрузка и сохранение данных сессии через middleware

  • Выбор из 19 серверных хранилищ для сессий, включая:

    • Базы данных: PostgreSQL, MySQL, MSSQL, SQLite
    • Кэш-системы: Redis
    • Поддержка пользовательских хранилищ
  • Расширенные функции:

    • Несколько сессий на один запрос
    • “Flash”-сообщения (одноразовые уведомления)
    • Регенерация токенов сессии
    • Таймауты: по бездействию и абсолютные
    • Функция “запомнить меня”
  • Гибкость:

    • Простота расширения и кастомизации
    • Передача токенов сессии через HTTP-заголовки или тела запросов/ответов
  • Производительность:

    • Оптимизированная архитектура
    • Меньший размер, выше скорость и меньше потребление памяти по сравнению с gorilla/sessions

    Установка

Этот пакет требует Go версии 1.12 или новее.

go get github.com/alexedwards/scs/v2

Примечание: Если вы используете традиционный механизм GOPATH для управления зависимостями (вместо модулей), вам нужно использовать go get и импортировать github.com/alexedwards/scs без суффикса v2.

Рекомендуется использовать версионные релизы. Код в ветке tip может содержать экспериментальные функции, которые могут измениться.

Базовое использование

SCS реализует механизм управления сессиями в соответствии с рекомендациями по безопасности OWASP. Данные сессии хранятся на сервере, а случайно сгенерированный уникальный токен сессии (или ID сессии) передается клиенту и обратно через cookie сессии.

package main

import (
	"io"
	"net/http"
	"time"

	"github.com/alexedwards/scs/v2"
)

var sessionManager *scs.SessionManager

func main() {
	// Инициализация нового менеджера сессий и настройка времени жизни сессии
	sessionManager = scs.New()
	sessionManager.Lifetime = 24 * time.Hour

	mux := http.NewServeMux()
	mux.HandleFunc("/put", putHandler)
	mux.HandleFunc("/get", getHandler)

	// Оберните ваши обработчики middleware LoadAndSave()
	http.ListenAndServe(":4000", sessionManager.LoadAndSave(mux))
}

func putHandler(w http.ResponseWriter, r *http.Request) {
	// Сохранение нового ключа и значения в данных сессии
	sessionManager.Put(r.Context(), "message", "Hello from a session!")
}

func getHandler(w http.ResponseWriter, r *http.Request) {
	// Использование вспомогательной функции GetString для получения строкового значения
	// по ключу. Возвращается нулевое значение, если ключ не существует.
	msg := sessionManager.GetString(r.Context(), "message")
	io.WriteString(w, msg)
}

Пример работы с curl:

$ curl -i --cookie-jar cj --cookie cj localhost:4000/put
HTTP/1.1 200 OK
Cache-Control: no-cache="Set-Cookie"
Set-Cookie: session=lHqcPNiQp_5diPxumzOklsSdE-MJ7zyU6kjch1Ee0UM; Path=/; Expires=Sat, 27 Apr 2019 10:28:20 GMT; Max-Age=86400; HttpOnly; SameSite=Lax
Vary: Cookie
Date: Fri, 26 Apr 2019 10:28:19 GMT
Content-Length: 0

$ curl -i --cookie-jar cj --cookie cj localhost:4000/get
HTTP/1.1 200 OK
Date: Fri, 26 Apr 2019 10:28:24 GMT
Content-Length: 21
Content-Type: text/plain; charset=utf-8

Hello from a session!

Настройка поведения сессии

Поведение сессии можно настроить через поля SessionManager:

sessionManager = scs.New()
sessionManager.Lifetime = 3 * time.Hour          // Общее время жизни сессии
sessionManager.IdleTimeout = 20 * time.Minute    // Таймаут бездействия
sessionManager.Cookie.Name = "session_id"        // Имя cookie
sessionManager.Cookie.Domain = "example.com"     // Домен cookie
sessionManager.Cookie.HttpOnly = true            // Доступ только через HTTP
sessionManager.Cookie.Path = "/example/"         // Путь cookie
sessionManager.Cookie.Persist = true             // Сохранение после закрытия браузера
sessionManager.Cookie.SameSite = http.SameSiteStrictMode // Политика SameSite
sessionManager.Cookie.Secure = true              // Только HTTPS
sessionManager.Cookie.Partitioned = true         // Partitioned cookies

Документация по всем доступным настройкам и их значениям по умолчанию доступна [здесь](ссылка на документацию).

Работа с данными сессии

Установка и получение данных

Данные можно устанавливать с помощью метода Put() и получать с помощью Get(). Для распространённых типов данных предусмотрены вспомогательные методы, такие как GetString(), GetInt() и GetBytes(). Полный список вспомогательных методов доступен в документации.

Одноразовое получение данных

Метод Pop() (и соответствующие вспомогательные методы для распространённых типов данных) работает как одноразовый Get() - извлекает данные и сразу удаляет их из сессии. Это полезно для реализации функционала “flash”-сообщений, которые показываются пользователю только один раз.

Дополнительные функции

  • Exists() - возвращает bool, указывающий на наличие ключа в данных сессии
  • Keys() - возвращает отсортированный срез всех ключей в данных сессии

Удаление данных

Отдельные элементы можно удалить с помощью метода Remove(). Для полной очистки данных сессии используйте метод Destroy(). После вызова Destroy() любые последующие операции в рамках того же цикла запроса приведут к созданию новой сессии - с новым токеном и временем жизни.

Хранение пользовательских типов

SCS использует кодировку gob для хранения данных сессии. Пользовательские типы должны быть зарегистрированы в пакете encoding/gob. Поля структур пользовательских типов должны быть экспортируемыми (начинаться с заглавной буквы), чтобы быть видимыми для пакета encoding/gob. Пример работы можно посмотреть [здесь](ссылка на пример).

Загрузка и сохранение сессий

Стандартное использование

Большинство приложений используют middleware LoadAndSave(). Этот middleware:

  • Загружает и сохраняет данные сессии в хранилище
  • Управляет передачей токена сессии клиенту через cookie

Кастомизация поведения

Если требуется изменить стандартное поведение (например, передавать токен сессии через HTTP-заголовки или устанавливать распределённую блокировку токена сессии на время запроса), можно создать собственный middleware, используя код LoadAndSave() в качестве шаблона. Пример доступен [здесь](ссылка на пример).

Точный контроль

Для более точного управления можно загружать и сохранять сессии непосредственно в обработчиках запросов или в любом другом месте приложения. Пример такого подхода приведён [здесь](ссылка на пример).

Настройка хранилища сессий

Хранилище по умолчанию

По умолчанию SCS использует in-memory хранилище для данных сессии. Это:

  • Удобно (не требует настройки)
  • Очень быстро
  • Но все данные теряются при остановке или перезапуске приложения

Это решение подходит для:

  • Приложений, где допустима потеря данных в обмен на высокую производительность
  • Прототипирования
  • Тестирования

Продукционные решения

Для большинства рабочих приложений рекомендуется использовать постоянные хранилища, такие как:

  • PostgreSQL
  • MySQL
  • Другие поддерживаемые системы (список ниже)

Полный список поддерживаемых хранилищ сессий с инструкциями по использованию доступен в таблице (ссылки в оригинальной документации).

Поддерживаемые хранилища сессий

Вот полный список доступных хранилищ сессий в SCS с их характеристиками:

Пакет Бэкенд Встроенный In-Memory Мультипроцессорный
badgerstore BadgerDB Да Нет Нет
boltstore BBolt Да Нет Нет
bunstore Bun ORM (PostgreSQL/MySQL/MSSQL/SQLite) Нет Нет Да
buntdbstore BuntDB Да Да Нет
cockroachdbstore CockroachDB Нет Нет Да
consulstore Consul Нет Да Да
etcdstore Etcd Нет Нет Да
firestore Google Cloud Firestore Нет ? Да
gormstore GORM ORM (PostgreSQL/MySQL/SQLite/MSSQL/TiDB) Нет Нет Да
leveldbstore LevelDB Да Нет Нет
memstore In-memory (по умолчанию) Да Да Нет
mongodbstore MongoDB Нет Нет Да
mssqlstore Microsoft SQL Server Нет Нет Да
mysqlstore MySQL Нет Нет Да
pgxstore PostgreSQL (драйвер pgx) Нет Нет Да
postgresstore PostgreSQL (драйвер pq) Нет Нет Да
redisstore Redis Нет Да Да
sqlite3store SQLite3 (CGO-драйвер mattn/go-sqlite3) Да Нет Да

Ключевые характеристики:

  • Встроенный - Не требует отдельного сервера/процесса
  • In-Memory - Хранит данные в оперативной памяти
  • Мультипроцессорный - Поддерживает работу в распределённой среде

Пользовательские хранилища

SCS также поддерживает создание собственных хранилищ сессий. Подробная информация доступна [здесь](ссылка на документацию).

Выбор хранилища зависит от требований вашего приложения:

  • Для тестирования/разработки - memstore или buntdbstore
  • Для продакшена - postgresstore, mysqlstore или redisstore
  • Для встраиваемых решений - badgerstore или boltstore

Использование пользовательских хранилищ сессий

Базовый интерфейс хранилища

Интерфейс scs.Store определяет контракт для пользовательских хранилищ сессий. Любой объект, реализующий этот интерфейс, может быть установлен как хранилище при настройке сессии.

type Store interface {
    // Delete удаляет токен сессии и соответствующие данные из хранилища.
    // Если токен не существует, Delete должен завершиться без ошибки.
    Delete(token string) (err error)

    // Find возвращает данные для указанного токена сессии.
    // Если токен не найден или истек, возвращает found=false.
    // Для повреждённых токенов также возвращает found=false.
    // Ошибка возвращается только для системных сбоев.
    Find(token string) (b []byte, found bool, err error)

    // Commit добавляет или обновляет данные сессии с указанным сроком действия.
    Commit(token string, b []byte, expiry time.Time) (err error)
}

type IterableStore interface {
    // All возвращает map со всеми активными (не истекшими) сессиями.
    // Ключ - токен сессии, значение - данные сессии.
    // Если активных сессий нет, возвращает пустую (не nil) map.
    All() (map[string][]byte, error)
}

Интерфейс с поддержкой контекста

scs.CtxStore расширяет базовый интерфейс, добавляя методы с поддержкой context.Context:

type CtxStore interface {
    Store

    // Версии методов с контекстом
    DeleteCtx(ctx context.Context, token string) (err error)
    FindCtx(ctx context.Context, token string) (b []byte, found bool, err error)
    CommitCtx(ctx context.Context, token string, b []byte, expiry time.Time) (err error)
}

type IterableCtxStore interface {
    // AllCtx - версия All с поддержкой контекста
    AllCtx(ctx context.Context) (map[string][]byte, error)
}

Защита от фиксации сессии

Для предотвращения атак фиксации сессии следует обновлять токен сессии при любом изменении уровня привилегий. Обычно это делается при входе/выходе пользователя:

func loginHandler(w http.ResponseWriter, r *http.Request) {
    userID := 123

    // 1. Сначала обновляем токен сессии
    err := sessionManager.RenewToken(r.Context())
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    // 2. Затем изменяем уровень привилегий
    sessionManager.Put(r.Context(), "userID", userID)
}

Важные моменты:

  1. RenewToken() должен вызываться ДО изменения данных сессии
  2. При ошибке обновления токена следует прервать операцию
  3. Такой же подход применяется при выходе пользователя

Этот механизм гарантирует, что после аутентификации сессия получает новый токен, делая недействительным любой ранее перехваченный злоумышленником токен.

Расширенные возможности SCS

Несколько сессий в одном запросе

SCS позволяет использовать несколько параллельных сессий в рамках одного запроса с разными:

  • Временем жизни
  • Хранилищами данных

Пример реализации доступен [здесь](ссылка на пример).

Перебор всех сессий

Для работы со всеми активными сессиями SCS предоставляет метод Iterate(), который принимает функцию-обработчик:

err := sessionManager.Iterate(r.Context(), func(ctx context.Context) error {
    userID := sessionManager.GetInt(ctx, "userID")
    
    if userID == 4 {
        // Удаляем сессию для пользователя с ID=4
        return sessionManager.Destroy(ctx)
    }
    
    return nil
})
if err != nil {
    log.Fatal(err)
}

Ключевые особенности:

  • Обработчик получает контекст каждой сессии
  • Можно выполнять любые операции с сессией
  • Возврат ошибки прерывает процесс итерации

Потоковая передача ответов (Flushing)

Поддержка потоковой передачи реализована через http.NewResponseController (доступно в Go ≥1.20):

func flushingHandler(w http.ResponseWriter, r *http.Request) {
    sessionManager.Put(r.Context(), "message", "Hello from flushing handler!")

    rc := http.NewResponseController(w)

    for i := 0; i < 5; i++ {
        fmt.Fprintf(w, "Write %d\n", i)
        
        err := rc.Flush()
        if err != nil {
            log.Println(err)
            return
        }

        time.Sleep(time.Second)
    }
}

Важно:

  • Стандартная реализация middleware LoadAndSave() не поддерживает интерфейс http.Flusher
  • Потоковая передача работает только в Go версии 1.20 и выше

Полный рабочий пример можно найти [здесь](ссылка на пример).

Совместимость с фреймворками

Возможны проблемы при интеграции с фреймворками, которые не передают контекст запроса через стандартные middleware:

  • Для Echo рекомендуется использовать пакет echo-scs-session
  • Fiber и другие нестандартные фреймворки могут требовать дополнительной адаптации

Вклад в разработку

Приветствуются:

  • Исправления ошибок
  • Улучшения документации

Для новых функций или изменений поведения:

  1. Создайте issue для обсуждения
  2. После согласования - отправляйте PR

Для новых реализаций хранилищ:

  • Как правило, не добавляются в основной репозиторий
  • Можно создать отдельный репозиторий и добавить ссылку в README через PR

1 - Официальное API SCS: Управление HTTP-сессиями для Go

Менеджер сессий для GO

Использование пользовательских хранилищ сеансов scs.Store определяет интерфейс для пользовательских хранилищ сеансов. Любой объект, реализующий этот интерфейс, может быть установлен как хранилище при настройке сеанса.

Работа с пользовательскими хранилищами сессий

Интерфейсы хранилищ

Базовый интерфейс Store

Определяет контракт для реализации пользовательских хранилищ:

type Store interface {
    // Delete удаляет токен и данные сессии из хранилища
    // Если токен не существует - операция должна завершиться успешно
    Delete(token string) error

    // Find ищет данные по токену сессии
    // Возвращает:
    // - данные (если найдены)
    // - флаг found (найдено/не найдено)
    // - ошибку (только для системных сбоев)
    Find(token string) ([]byte, bool, error)

    // Commit сохраняет или обновляет данные сессии
    Commit(token string, data []byte, expiry time.Time) error
}

Интерфейс IterableStore

Добавляет возможность перебора всех сессий:

type IterableStore interface {
    // All возвращает все активные (не истекшие) сессии
    // В формате map[токен]данные
    All() (map[string][]byte, error)
}

Версии с поддержкой контекста

CtxStore

Расширяет базовый интерфейс с добавлением context.Context:

type CtxStore interface {
    Store
    
    // Версии методов с поддержкой контекста
    DeleteCtx(ctx context.Context, token string) error
    FindCtx(ctx context.Context, token string) ([]byte, bool, error) 
    CommitCtx(ctx context.Context, token string, data []byte, expiry time.Time) error
}

IterableCtxStore

Аналогично для перебора сессий:

type IterableCtxStore interface {
    AllCtx(ctx context.Context) (map[string][]byte, error)
}

Защита от фиксации сессии

Для предотвращения атак фиксации сессии необходимо:

func loginHandler(w http.ResponseWriter, r *http.Request) {
    userID := 123

    // 1. Сначала обновляем токен сессии
    if err := sessionManager.RenewToken(r.Context()); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // 2. Затем сохраняем данные пользователя
    sessionManager.Put(r.Context(), "userID", userID)
}

Ключевые моменты:

  1. Всегда обновляйте токен при изменении прав доступа
  2. Порядок операций критически важен
  3. Такой же подход применяйте при выходе пользователя

Это гарантирует, что после аутентификации будет создан новый токен сессии, делая недействительными любые ранее перехваченные токены.

Типы данных в SCS

Интерфейс Codec

Добавлен в v2.2.0

type Codec interface {
    // Encode преобразует срок действия и значения сессии в байтовый срез
    Encode(deadline time.Time, values map[string]interface{}) ([]byte, error)
    
    // Decode восстанавливает срок действия и значения сессии из байтового среза
    Decode([]byte) (deadline time.Time, values map[string]interface{}, err error)
}

Интерфейс для кодирования/декодирования данных сессии при работе с хранилищем.

Интерфейс CtxStore

Добавлен в v2.5.0

type CtxStore interface {
    Store
    
    // Версии методов с поддержкой контекста:
    DeleteCtx(ctx context.Context, token string) error
    FindCtx(ctx context.Context, token string) ([]byte, bool, error)
    CommitCtx(ctx context.Context, token string, b []byte, expiry time.Time) error
}

Расширенный интерфейс хранилища с поддержкой context.Context.

Структура GobCodec

Добавлена в v2.3.1

type GobCodec struct{}

Реализация Codec с использованием encoding/gob для сериализации данных.

Методы GobCodec:

// Decode преобразует байты в срок действия и данные сессии
func (GobCodec) Decode(b []byte) (time.Time, map[string]interface{}, error)

// Encode сериализует данные сессии в байтовый срез  
func (GobCodec) Encode(deadline time.Time, values map[string]interface{}) ([]byte, error)

Интерфейс IterableCtxStore

Добавлен в v2.5.0

type IterableCtxStore interface {
    // AllCtx возвращает все активные сессии (с поддержкой контекста)
    AllCtx(ctx context.Context) (map[string][]byte, error)
}

Интерфейс для перечислимых хранилищ с поддержкой context.Context.

Интерфейс IterableStore

Добавлен в v2.5.0

type IterableStore interface {
    // All возвращает все активные (не истекшие) сессии
    All() (map[string][]byte, error)
}

Базовый интерфейс для хранилищ с возможностью перебора сессий.

Ключевые особенности:

  • Codec - абстракция для сериализации данных
  • GobCodec - стандартная реализация через encoding/gob
  • CtxStore добавляет поддержку контекста к базовому хранилищу
  • Интерфейсы Iterable позволяют работать со всеми сессиями

Конфигурация сессий в SCS

Структура SessionCookie

type SessionCookie struct {
    // Имя cookie сессии (не должно содержать спецсимволы)
    // По умолчанию: "session"
    Name string

    // Домен cookie (по умолчанию - текущий домен)
    Domain string

    // HttpOnly флаг (по умолчанию true)
    HttpOnly bool

    // Путь cookie (по умолчанию "/")
    Path string

    // Сохранять cookie после закрытия браузера (по умолчанию true)
    Persist bool

    // Политика SameSite (по умолчанию Lax)
    SameSite http.SameSite

    // Secure флаг (только HTTPS, по умолчанию false)
    Secure bool
}

Настройки cookie для управления сессиями.

Структура SessionManager

Добавлена в v2.1.0

type SessionManager struct {
    // Таймаут бездействия (опционально)
    IdleTimeout time.Duration

    // Максимальное время жизни сессии (по умолчанию 24 часа)
    Lifetime time.Duration

    // Хранилище сессий
    Store Store

    // Настройки cookie
    Cookie SessionCookie

    // Кодек для сериализации данных (по умолчанию GobCodec)
    Codec Codec

    // Обработчик ошибок (по умолчанию HTTP 500)
    ErrorFunc func(http.ResponseWriter, *http.Request, error)

    // Хэшировать токен в хранилище
    HashTokenInStore bool
    // содержит скрытые поля
}

Основные настройки:

  • IdleTimeout: автоматическое завершение неактивных сессий
  • Lifetime: абсолютное время жизни сессии
  • Store: подключение к Redis, PostgreSQL и другим хранилищам
  • Cookie: тонкая настройка параметров безопасности cookie
  • Codec: кастомная сериализация данных
  • ErrorFunc: обработка ошибок на уровне middleware

Рекомендации по безопасности:

  1. Всегда устанавливайте Secure=true в production
  2. Используйте SameSite=Strict для критичных операций
  3. Для API можно отключить HttpOnly и работать через заголовки
  4. Регулируйте Lifetime в соответствии с требованиями приложения

Пример инициализации:

manager := scs.New()
manager.Lifetime = 12 * time.Hour
manager.Cookie.Secure = true
manager.Cookie.SameSite = http.SameSiteStrictMode
manager.Store = redisstore.New(redisPool)

Методы SessionManager

Основные функции

New

Добавлено в v2.1.0

func New() *SessionManager

Создает новый менеджер сессий с настройками по умолчанию. Потокобезопасен.

Clear (устаревший)

func (s *SessionManager) Clear(ctx context.Context) error

Очищает все данные текущей сессии, не затрагивая токен и время жизни. Если данных нет - операция не выполняется.

Управление сессиями

Commit

Добавлено в v2.1.0

func (s *SessionManager) Commit(ctx context.Context) (string, time.Time, error)

Сохраняет данные сессии в хранилище и возвращает:

  • Токен сессии
  • Время истечения
  • Ошибку (если есть)

Обычно используется автоматически middleware LoadAndSave().

Deadline

Добавлено в v2.5.0

func (s *SessionManager) Deadline(ctx context.Context) time.Time

Возвращает абсолютное время истечения сессии. При использовании IdleTimeout сессия может завершиться раньше из-за неактивности.

Destroy

Добавлено в v2.1.0

func (s *SessionManager) Destroy(ctx context.Context) error

Полностью удаляет сессию:

  1. Удаляет данные из хранилища
  2. Помечает сессию как уничтоженную
  3. Новые операции создадут свежую сессию

Работа с данными

Exists

Добавлено в v2.1.0

func (s *SessionManager) Exists(ctx context.Context, key string) bool

Проверяет наличие ключа в данных сессии.

Get

Добавлено в v2.1.0

func (s *SessionManager) Get(ctx context.Context, key string) interface{}

Возвращает значение по ключу как interface{}, требующее приведения типа:

foo, ok := session.Get(ctx, "foo").(string)
if !ok {
    return errors.New("ошибка приведения типа")
}

GetBool

Добавлено в v2.1.0

func (s *SessionManager) GetBool(ctx context.Context, key string) bool

Возвращает значение как bool (по умолчанию false если ключ отсутствует или тип не совпадает).

GetBytes

Добавлено в v2.1.0

func (s *SessionManager) GetBytes(ctx context.Context, key string) []byte

Возвращает значение как []byte (по умолчанию nil).

Методы работы с данными сессии

Получение типизированных значений

GetFloat

func (s *SessionManager) GetFloat(ctx context.Context, key string) float64

Возвращает значение как float64 (0 если ключ отсутствует или тип не совпадает)

GetInt

func (s *SessionManager) GetInt(ctx context.Context, key string) int  

Возвращает значение как int (0 если ключ отсутствует)

GetInt32

func (s *SessionManager) GetInt32(ctx context.Context, key string) int32

Возвращает значение как int32 (0 по умолчанию)

GetInt64

func (s *SessionManager) GetInt64(ctx context.Context, key string) int64

Возвращает значение как int64 (0 по умолчанию)

GetString

func (s *SessionManager) GetString(ctx context.Context, key string) string

Возвращает строковое значение (пустая строка "" если ключ отсутствует)

GetTime

func (s *SessionManager) GetTime(ctx context.Context, key string) time.Time

Возвращает значение времени (time.IsZero() == true если ключ отсутствует)

Управление сессиями

Iterate

func (s *SessionManager) Iterate(ctx context.Context, fn func(context.Context) error) error

Итерируется по всем активным сессиям и выполняет функцию fn для каждой. Требует поддержки итерации в хранилище.

Keys

func (s *SessionManager) Keys(ctx context.Context) []string

Возвращает отсортированный список всех ключей сессии (пустой слайс если данных нет)

Middleware и загрузка данных

Load

func (s *SessionManager) Load(ctx context.Context, token string) (context.Context, error)

Загружает данные сессии по токену и возвращает новый контекст. Создает новую сессию если токен не найден.

LoadAndSave

func (s *SessionManager) LoadAndSave(next http.Handler) http.Handler

Middleware для автоматической загрузки/сохранения сессии и управления cookie.

Пример:

router := http.NewServeMux()
router.HandleFunc("/", handler)

// Обертывание роутера middleware
app := sessionManager.LoadAndSave(router)

http.ListenAndServe(":4000", app)

Методы управления сессиями в SCS

Работа с данными сессии

MergeSession (v2.5.0+)

func (s *SessionManager) MergeSession(ctx context.Context, token string) error

Объединяет данные из другой сессии (полезно при OAuth-редиректах). Для полной замены данных используйте Clear().

Pop-методы

Одноразовое получение данных с удалением ключа:

func (s *SessionManager) Pop(ctx context.Context, key string) interface{}
func (s *SessionManager) PopBool(ctx context.Context, key string) bool
func (s *SessionManager) PopBytes(ctx context.Context, key string) []byte  
func (s *SessionManager) PopFloat(ctx context.Context, key string) float64
func (s *SessionManager) PopInt(ctx context.Context, key string) int
func (s *SessionManager) PopString(ctx context.Context, key string) string
func (s *SessionManager) PopTime(ctx context.Context, key string) time.Time

Пример для flash-сообщений:

// Установка
sessionManager.Put(ctx, "flash", "Сообщение")

// Получение с удалением  
msg := sessionManager.PopString(ctx, "flash")

Основные операции

Put (v2.1.0+)

func (s *SessionManager) Put(ctx context.Context, key string, val interface{})

Добавляет или обновляет значение в сессии. Автоматически помечает сессию как измененную.

Remove (v2.1.0+)

func (s *SessionManager) Remove(ctx context.Context, key string)

Удаляет ключ из сессии. Если ключ не существует - операция игнорируется.

Управление токенами и временем жизни

RenewToken (v2.1.0+)

func (s *SessionManager) RenewToken(ctx context.Context) error

Генерирует новый токен сессии, сохраняя данные. Критично для:

  • Входа/выхода пользователей
  • Изменения прав доступа
  • Защиты от фиксации сессии

RememberMe (v2.5.0+)

func (s *SessionManager) RememberMe(ctx context.Context, val bool)

Управляет постоянством сессии (работает только при Cookie.Persist = false).

SetDeadline (v2.7.0+)

func (s *SessionManager) SetDeadline(ctx context.Context, expire time.Time)

Устанавливает абсолютное время истечения сессии (может быть перекрыто IdleTimeout).

Информационные методы

Status (v2.1.0+)

func (s *SessionManager) Status(ctx context.Context) Status

Возвращает текущее состояние сессии (новые/измененные/уничтоженные).

Token (v2.5.0+)

func (s *SessionManager) Token(ctx context.Context) string

Возвращает токен сессии (пустую строку до коммита).

WriteSessionCookie (v2.3.0+)

func (s *SessionManager) WriteSessionCookie(ctx context.Context, w http.ResponseWriter, token string, expiry time.Time)

Низкоуровневый метод записи cookie (обычно используется через middleware).

Типы данных и интерфейсы SCS

Тип Status

type Status int

Статус представляет состояние данных сессии в течение цикла запроса.

Константы статусов:

const (
    // Unmodified - данные сессии не изменялись
    Unmodified Status = iota
    
    // Modified - данные были изменены
    Modified
    
    // Destroyed - сессия была уничтожена
    Destroyed
)

Использование:

status := sessionManager.Status(ctx)
switch status {
case scs.Unmodified:
    // Сессия не изменялась
case scs.Modified:
    // Требуется сохранение изменений  
case scs.Destroyed:
    // Сессия закрыта
}

Интерфейс Store

type Store interface {
    // Delete удаляет токен и данные сессии
    // Если токен не существует - операция игнорируется
    Delete(token string) error

    // Find ищет данные по токену сессии
    // Возвращает:
    // - данные (если найдены)
    // - флаг существования
    // - ошибку (только для системных сбоев)
    Find(token string) ([]byte, bool, error)

    // Commit сохраняет/обновляет данные сессии
    Commit(token string, data []byte, expiry time.Time) error
}

Базовый интерфейс для реализации хранилищ сессий.

Особенности реализации:

  1. Delete должен быть идемпотентным
  2. Find возвращает found=false для:
    • Несуществующих токенов
    • Истекших сессий
    • Поврежденных данных
  3. Commit должен перезаписывать существующие данные

Пример проверки сессии:

data, found, err := store.Find(token)
if err != nil {
    // Обработка системной ошибки
}
if !found {
    // Сессия не существует/истекла
}

Этот интерфейс позволяет интегрировать SCS с любыми системами хранения данных.