golang

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

  • воскресенье, 2 марта 2025 г. в 00:00:05
https://habr.com/ru/articles/887014/

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

Куки (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-атак:

  • Lax — куки отправляются только при переходах через ссылку.

  • Strict — куки отправляются только при навигации в рамках одного домена.

  • None — куки передаются всегда, но только с Secure: true.

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

Для защиты содержимого кук можно использовать 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, а также подпись данных помогают защититься от атак и утечек данных. Если вам нужна безопасная аутентификация, рассмотрите альтернативы вроде JWT или серверных сессий.

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