1 changed files with 44 additions and 0 deletions
@ -0,0 +1,44 @@ |
|||
import svgCaptcha from 'svg-captcha' |
|||
|
|||
interface CaptchaRecord { |
|||
text: string |
|||
createdAt: number |
|||
} |
|||
|
|||
const captchaStore = new Map<string, CaptchaRecord>() |
|||
const CAPTCHA_TTL = 5 * 60 * 1000 |
|||
|
|||
function cleanupExpired(): void { |
|||
const now = Date.now() |
|||
for (const [token, record] of captchaStore) { |
|||
if (now - record.createdAt > CAPTCHA_TTL) { |
|||
captchaStore.delete(token) |
|||
} |
|||
} |
|||
} |
|||
|
|||
export function generateCaptcha(): { token: string; svg: string } { |
|||
cleanupExpired() |
|||
const { text, data: svg } = svgCaptcha.create({ |
|||
noise: 3, |
|||
color: true, |
|||
background: '#f8f9fa', |
|||
}) |
|||
const token = crypto.randomUUID() |
|||
captchaStore.set(token, { text, createdAt: Date.now() }) |
|||
return { token, svg } |
|||
} |
|||
|
|||
export function verifyCaptcha(token: string, text: string): boolean { |
|||
const record = captchaStore.get(token) |
|||
if (!record) return false |
|||
if (Date.now() - record.createdAt > CAPTCHA_TTL) { |
|||
captchaStore.delete(token) |
|||
return false |
|||
} |
|||
const match = record.text.toLowerCase() === text.toLowerCase() |
|||
if (match) { |
|||
captchaStore.delete(token) |
|||
} |
|||
return match |
|||
} |
|||
Loading…
Reference in new issue