ViraStack
  • Akademi
  • Hakkında
  • Destek
Genel BakışBaşlangıçÖrnekler

Başlangıç

  • Giriş
  • 1.0'dan geçiş
  • llms.txt
  • llms-full.txt

Kullanım

  • useViraPassword()
  • Güç
  • Parola tekrarı
  • React Hook Form
  • Erişilebilirlik
  • Özelleştirme

Sunucu

  • Sunucu doğrulaması
  • Sızmış parolalar

Başvuru

  • Yardımcılar
  • Tipler
  • UI kütüphaneleri
  • Karşılaştırma

Güç

@virastack/password/strength ile NIST tarzı parola politikası: uzunluk, yaygın parolalar, tekrarlar ve kişisel bilgi.

definePolicy()

Politikayı "use client" içermeyen ortak bir dosyada bir kez tanımlayın. Form ve sunucu aynı nesneyi import eder.

// lib/password-policy.ts
// Shared by the form and the server, so no "use client".
import { definePolicy } from "@virastack/password/strength";
 
export const policy = definePolicy({ preset: "nist", blocklist: ["virastack"] });

Şablonlar

ŞablonUzunlukBileşim
nist (varsayılan)15–64Yok. NIST SP 800-63B-4'e göre: uzunluk ve yasak liste, bileşim kuralı yok
legacy8–64Küçük harf, büyük harf, rakam ve sembol

Şablonun her değeri değiştirilebilir:

definePolicy({ preset: "nist", minLength: 8 }) // ikinci faktörle (MFA)
definePolicy({ preset: "legacy", require: { symbol: false } })
definePolicy({ blocklist: ["acme", "acme pay"] }) // ürün adınız, herhangi bir yerde
definePolicy({ minTokenLength: 4 }) // kısa adlarda daha az yanlış pozitif
definePolicy({ blockCommon: false, blockRepetitive: false })

Çakışan kurallar (örneğin maxLength'ten büyük minLength) politika tanımlanırken hata fırlatır.

Sonuç

import { evaluate } from "@virastack/password/strength"
import { policy } from "@/lib/password-policy"
 
evaluate("correct horse battery staple", policy)
// {
//   score: 0,            // 0–1 politikayı geçmez, 2–4 geçer
//   level: "weak",       // "weak" | "fair" | "good" | "strong"
//   length: 28,          // NFKC sonrası karakter (code point)
//   valid: false,
//   checks: { minLength: true, maxLength: true, notCommon: false, ... },
//   issues: ["password.common"],
// }
AnahtarNe zaman
password.tooShort / tooLongminLength–maxLength dışında
password.noLowercase / noUppercase / noDigit / noSymbolGerekli bir karakter sınıfı eksik (legacy)
password.commonYaygın bir parola; etrafında rakam, sembol veya leetspeak olsa bile
password.blockedPolitikanın blocklist'indeki bir kelimeyi içerir
password.repetitiveTekrar veya dizi: aaaa…, abcabc…, 12345…, qwerty…
password.containsPersonalInfoforbidden değerlerinden birini içerir

Skor, uzunluk ve karakter çeşitliliğinden çıkan bir sezgiseldir; kırılma süresi tahmini değildir. Onun için karşılaştırmaya bakın.

Karmaşık bir 14 karakterlik parola neden zayıf? Skor evrensel bir kurala değil, politikaya göre hesaplanır. Varsayılan nist şablonu 15 karakter ister; daha kısa parolalar ne kadar karışık olursa olsun politikayı geçemez ve 0–1 alır. 15 karakterden sonra skor uzunluk ve çeşitlilikle artar. Daha kısa parola mı gerekiyor? minLength: 8 (NIST ikinci faktörle buna izin verir) veya legacy şablonunu kullanın.

Hook içinde

policy verin; strength, issues ve strengthProps alanlarını okuyun. Hook motoru import etmez; motor politikayla gelir, yani yalnızca toggle kullanan sayfa onu indirmez.

15 characters or more

// components/new-password-field.tsx
"use client";
 
import { useViraPassword } from "@virastack/password";
 
import { passwordMessages } from "@/lib/password-messages";
import { policy } from "@/lib/password-policy";
 
// Filled bars per level
const bars = { weak: 1, fair: 2, good: 3, strong: 4 };
 
export function NewPasswordField() {
  const { inputProps, btnProps, strength, strengthProps, issues } = useViraPassword({ policy });
  const typed = (strength?.length ?? 0) > 0;
  const filled = typed && strength ? bars[strength.level] : 0;
 
  return (
    <>
      <label htmlFor={inputProps.id}>New password</label>
      <div>
        <input {...inputProps} />
        <button {...btnProps} />
      </div>
 
      {/* The bar is yours: the hook only gives the level. */}
      <div data-level={strength?.level}>
        {[1, 2, 3, 4].map((step) => (
          <span key={step} data-filled={step <= filled} />
        ))}
      </div>
      <p {...strengthProps}>{typed ? `Strength: ${strength?.level}` : "15 characters or more"}</p>
 
      {typed && (
        <ul>
          {issues.map((issue) => (
            <li key={issue}>{passwordMessages[issue]}</li>
          ))}
        </ul>
      )}
    </>
  );
}

forbidden

Paket kullanıcınızı bilmez; değerleri siz verirsiniz. Eşleştirme büyük/küçük harfi, aksanı ve basit leetspeak'i yok sayar.

evaluate(password, policy, { forbidden: [email, name, username] })
// "hello@virastack.com" → "hello" (alan adı yok sayılır)
// "Vira Stack" → "vira stack", "vira", "stack"

minTokenLength'ten (varsayılan 3) kısa parçalar yok sayılır. Kısa parçalar yanlış pozitife yol açar: dev@virastack.com için dev parçası devoted-garden-path parolasını reddeder. Sizin için önemliyse 4'e çıkarın.

Try vira-garden-path

// components/new-password-field.tsx
"use client";
 
import { useState } from "react";
 
import { useViraPassword } from "@virastack/password";
 
import { passwordMessages } from "@/lib/password-messages";
import { policy } from "@/lib/password-policy";
 
export function NewPasswordField() {
  const [email, setEmail] = useState("hello@virastack.com");
  const [name, setName] = useState("Vira Stack");
 
  // Email: the local part and its pieces ("hello"). Name: each word ("vira", "stack").
  const { inputProps, btnProps, issues, strengthProps } = useViraPassword({
    policy,
    forbidden: [email, name],
  });
 
  return (
    <>
      <label htmlFor="forbidden-email">Email</label>
      <input
        id="forbidden-email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
      />
 
      <label htmlFor="forbidden-name">Name</label>
      <input id="forbidden-name" value={name} onChange={(event) => setName(event.target.value)} />
 
      <label htmlFor={inputProps.id}>New password</label>
      <div>
        <input {...inputProps} />
        <button {...btnProps} />
      </div>
 
      <p {...strengthProps}>
        {issues.includes("password.containsPersonalInfo")
          ? passwordMessages["password.containsPersonalInfo"]
          : "Try vira-garden-path"}
      </p>
    </>
  );
}

Unicode

  • Parola NFKC ile normalleştirilir; farklı klavyelerde yazılan aynı metin aynı sonucu verir.
  • Uzunluk code point sayar: bir emoji veya Türkçe harf bir kez sayılır.
  • Sıfır genişlikli karakterler uzunluğa sayılmaz.
  • maxLength'te hiçbir şey kesilmez; uzun parola password.tooLong alır.

Yapıştırma

Parola alanlarına yapıştırmayı engellemeyin. Parola yöneticileri buna dayanır ve NIST izin verilmesini önerir. Hook yapıştırmayı asla engellemez.

ÖncekiuseViraPassword()SonrakiParola tekrarı

Bu sayfada

  • definePolicy()
  • Şablonlar
  • Sonuç
  • Hook içinde
  • forbidden
  • Unicode
  • Yapıştırma
Hata mı var? Düzeltin