Как стать автором
Обновить

Как работать с cookie в Go: безопасное хранение и управление сессиями

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров1.9K

Автор статьи: Якушков Федор

Куки (HTTP Cookies) используются для хранения данных на стороне клиента, например, для аутентификации, управления сессиями или персонализации контента. В языке Go работа с куками реализована через стандартную библиотеку net/http, что делает их использование простым и удобным. В этой статье мы разберем основные операции с куками в Go, а также рассмотрим аспекты их безопасности.

Основные операции с куками в Go

Установка кук

Чтобы установить куку в ответе сервера, нужно использовать заголовок Set-Cookie. В Go для этого используется http.SetCookie():

package main

import (
    "net/http"
)

func setCookieHandler(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name:     "session_id",
        Value:    "123456",
        Path:     "/",
        HttpOnly: true, // Доступ только через HTTP, защита от XSS
        Secure:   true, // Только HTTPS
        SameSite: http.SameSiteStrictMode, // Защита от CSRF
    }
    http.SetCookie(w, cookie)
    w.Write([]byte("Cookie set!"))
}

func main() {
    http.HandleFunc("/set-cookie", setCookieHandler)
    http.ListenAndServe(":8080", nil)
}

Этот обработчик устанавливает куку session_id с безопасными параметрами:

  • HttpOnly: true — запретит доступ к куке из JavaScript (защита от XSS-атак).

  • Secure: true — кука будет передаваться только по HTTPS.

  • SameSite: Strict — защита от CSRF-атак.

Чтение кук

Куки передаются в заголовке Cookie и доступны в http.Request через метод r.Cookie():

func getCookieHandler(w http.ResponseWriter, r *http.Request) {
    cookie, err := r.Cookie("session_id")
    if err != nil {
        http.Error(w, "Cookie not found", http.StatusNotFound)
        return
    }
    w.Write([]byte("Cookie value: " + cookie.Value))
}

func main() {
    http.HandleFunc("/get-cookie", getCookieHandler)
    http.ListenAndServe(":8080", nil)
}

Удаление кук

Чтобы удалить куку, нужно установить ее с истекшим сроком:

func deleteCookieHandler(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name:   "session_id",
        Value:  "",
        Path:   "/",
        MaxAge: -1, // Удаление куки
    }
    http.SetCookie(w, cookie)
    w.Write([]byte("Cookie deleted!"))
}

Безопасность кук

HttpOnly и Secure

Использование HttpOnly и Secure предотвращает кражу кук через JavaScript (document.cookie) и защищает их от передачи через HTTP.

SameSite и CSRF

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

  • SameSite=Lax: Куки отправляются при переходах по безопасным HTTP-методам (GET) и в некоторых других случаях, например, при загрузке изображений.

  • SameSite=Strict: Куки отправляются только при запросах, инициированных с того же домена. Этот режим обеспечивает наиболее сильную защиту от CSRF, но может нарушить удобство использования в некоторых сценариях.

  • SameSite=None: Куки отправляются всегда, независимо от того, откуда был инициирован запрос. Этот режим требует обязательного использования атрибута Secure=true, так как куки передаются только по HTTPS.

Для надежной защиты от CSRF необходимо использовать CSRF-токены. Это случайные значения, которые сервер генерирует и отправляет клиенту. При каждом запросе, изменяющем состояние сервера, клиент должен отправлять этот токен. Сервер проверяет соответствие токена, чтобы убедиться, что запрос был сделан намеренно.

Подпись и шифрование кук

Для защиты содержимого кук можно использовать gorilla/securecookie:

import (
    "encoding/gob"
    "github.com/gorilla/securecookie"
)

var hashKey = []byte("super-secret-key")
var s = securecookie.New(hashKey, nil)

type SessionData struct {
    Username string
}

gob.Register(SessionData{})

func setSignedCookie(w http.ResponseWriter) {
    value := SessionData{Username: "user123"}
    encoded, _ := s.Encode("session", value)
    cookie := &http.Cookie{Name: "session", Value: encoded, Path: "/", HttpOnly: true}
    http.SetCookie(w, cookie)
}

Заключение

Работа с куками в Go требует внимательного отношения к безопасности. Использование атрибутов HttpOnly, Secure и SameSite помогает снизить риск атак, таких как XSS и CSRF. Однако, важно понимать, что SameSite не является полной защитой от CSRF и должен использоваться в сочетании с CSRF-токенами. Для защиты конфиденциальных данных в куках рекомендуется использовать подпись и шифрование.

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

Код можно протестировать, запустив сервер на http://localhost:8080 и проверяя установку, получение и удаление кук.

Теги:
Хабы:
Всего голосов 8: ↑4 и ↓4+2
Комментарии6

Публикации

Работа

Go разработчик
83 вакансии

Ближайшие события