/
Alcatraz
/
Wagomon
Обзор
Документация
Войти
/
Alcatraz
/
Wagomon
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/lib/server/captcha.js
77 строк
2 KB
saitgalineu
start
25 фев 2026, 16:24
25 фев 2026, 16:24
e8a3e93
Код
Авторство
О чём код?
import crypto from 'crypto'; const CAPTCHA_COOKIE_NAME = 'captcha'; function getSecret() { const secret = process.env.SESSION_SECRET; if (!secret) { throw new Error('SESSION_SECRET is not set'); } return secret; } function createCaptcha() { const rand = () => Math.floor(Math.random() * 101); const a = rand(); const b = rand(); const op = '+'; return { a, b, op }; } function signCaptcha(data) { const secret = getSecret(); const json = JSON.stringify(data); const hmac = crypto.createHmac('sha256', secret).update(json).digest('hex'); return Buffer.from(JSON.stringify({ d: data, s: hmac })).toString('base64url'); } function verifyCaptcha(value) { if (!value) return null; try { const secret = process.env.SESSION_SECRET; if (!secret) return null; const decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8')); const { d, s } = decoded; const expected = crypto.createHmac('sha256', secret).update(JSON.stringify(d)).digest('hex'); if (expected !== s) return null; return d; } catch { return null; } } function setCaptchaCookie(cookies, data) { const value = signCaptcha(data); cookies.set(CAPTCHA_COOKIE_NAME, value, { path: '/login', httpOnly: true, sameSite: 'lax', secure: false }); } function readCaptchaCookie(cookies) { const value = cookies.get(CAPTCHA_COOKIE_NAME); if (!value) return null; return verifyCaptcha(value); } export function getOrCreateCaptcha(cookies) { let captcha = readCaptchaCookie(cookies); if (!captcha) { captcha = createCaptcha(); setCaptchaCookie(cookies, captcha); } return captcha; } export function rotateCaptcha(cookies) { const captcha = createCaptcha(); setCaptchaCookie(cookies, captcha); return captcha; } export function readCaptchaForVerification(cookies) { return readCaptchaCookie(cookies); }