Fresh — фреймворк для Deno, ориентированный на серверный рендеринг и минимальный JavaScript на клиенте. Работа с cookies в Fresh происходит полностью на сервере, что делает их ключевым инструментом для аутентификации, хранения сессий и передачи небольших фрагментов состояния между запросами. Безопасность cookies в этом контексте имеет принципиальное значение, так как они автоматически отправляются браузером при каждом HTTP-запросе.
Fresh не навязывает собственную реализацию cookies, а опирается на стандартные HTTP-механизмы и утилиты Deno, что даёт полный контроль над параметрами безопасности.
Неправильно настроенные cookies могут привести к следующим проблемам:
Защита строится на корректной настройке атрибутов cookies и архитектуре серверной логики.
Атрибут HttpOnly запрещает доступ к cookie из JavaScript
(document.cookie). Это критично для защиты от XSS.
Set-Cookie: session=abc123; HttpOnly
В Fresh это означает, что даже при наличии интерактивных island-компонентов клиентский код не сможет прочитать или изменить cookie.
Атрибут Secure указывает браузеру отправлять cookie
только по HTTPS.
Set-Cookie: session=abc123; Secure
В production-окружении Fresh почти всегда разворачивается за HTTPS (Deno Deploy, Cloudflare, Vercel), поэтому этот флаг должен использоваться по умолчанию для всех чувствительных cookies.
SameSite определяет, будет ли cookie отправляться при
кросс-сайтовых запросах.
Варианты:
Secure)Set-Cookie: session=abc123; SameSite=Strict
Для сессионных cookies в Fresh чаще всего используется
Strict или Lax, что существенно снижает риск
CSRF.
Path ограничивает URL-пространство, где cookie будет
доступнаDomain ограничивает домен и поддоменыSet-Cookie: session=abc123; Path=/; Domain=example.com
Минимизация области действия cookie снижает потенциальный ущерб при утечке.
Fresh использует стандартный Response API. Cookies
устанавливаются через HTTP-заголовок Set-Cookie.
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
GET(_req, ctx) {
const headers = new Headers();
headers.append(
"Set-Cookie",
"session=abc123; HttpOnly; Secure; SameSite=Strict; Path=/",
);
return new Response("OK", { headers });
},
};
Каждый атрибут задаётся явно, что исключает неявные или небезопасные значения.
Cookies доступны через заголовок Cookie входящего
запроса.
const cookieHeader = req.headers.get("cookie");
Для удобства обычно используется парсер:
function parseCookies(cookieHeader: string | null) {
if (!cookieHeader) return {};
return Object.fromEntries(
cookieHeader.split("; ").map((c) => c.split("=")),
);
}
Такой подход подчёркивает сервероцентричную модель Fresh: все решения о доступе и валидации принимаются до рендера страницы.
Для аутентификации часто применяются сессионные cookies, срок жизни которых ограничен:
Set-Cookie: session=abc123; Max-Age=3600
или
Set-Cookie: session=abc123; Expires=Wed, 21 Oct 2026 07:28:00 GMT
Короткое время жизни снижает риск использования украденного значения.
Удаление производится установкой того же имени cookie с истёкшим сроком действия:
Set-Cookie: session=; Max-Age=0; Path=/
В Fresh это реализуется тем же механизмом заголовков ответа.
Cookies никогда не должны содержать:
Обычно в cookie хранится только непрозрачный идентификатор сессии, а все данные находятся на сервере или в базе.
Для защиты от подмены используется криптографическая подпись:
Пример логики:
Даже при утечке cookie злоумышленник не сможет сгенерировать валидное значение.
Islands в Fresh исполняются на клиенте, но не имеют доступа к HttpOnly cookies. Это естественным образом разделяет ответственность:
Такая модель снижает поверхность атаки без дополнительных библиотек.
HttpOnly у сессионных cookiesSameSite=None без необходимостиSecure в productionDomain и PathКаждая из этих ошибок увеличивает риск компрометации сессий.
Минимально безопасный набор для сессионной cookie в Fresh:
Set-Cookie: session=<id>; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600
Такое сочетание закрывает основные векторы атак и хорошо сочетается с архитектурой Fresh, где сервер является единственной точкой принятия решений.