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

Sunucu doğrulaması

Aynı politikayı @virastack/password/server ile Server Action ve API route'larda çalıştırın.

Sunucu girişi

Tarayıcı atlanabilir; karar sunucudadır. validatePassword formla aynı motoru kullanır; aynı girdi iki tarafta aynı hataları verir. Kayıt, parola sıfırlama ve parola değiştirmede kullanın.

import { validatePassword } from "@virastack/password/server"
 
const result = validatePassword(formData.get("password"), policy, {
  forbidden: [formData.get("email")],
  confirm: formData.get("confirm"), // farklıysa password.mismatch ekler
})
// result.valid, result.issues, result.score, result.password (NFKC)

String olmayan her şey (eksik alan, File) boş parola sayılır.

Server Action

// components/signup-form.tsx
"use client";
 
import { useActionState, useState } from "react";
 
import { useViraPassword } from "@virastack/password";
 
import { passwordMessages } from "@/lib/password-messages";
import { policy } from "@/lib/password-policy";
import { signup, type SignupState } from "@/app/signup/actions";
 
export function SignupForm() {
  const [state, action, pending] = useActionState<SignupState, FormData>(signup, null);
  const [password, setPassword] = useState("");
 
  // No form library: plain state; the form still posts its own FormData.
  const { inputProps, btnProps } = useViraPassword({
    policy,
    inputProps: {
      name: "password",
      value: password,
      onChange: (event) => setPassword(event.target.value),
    },
  });
  const { inputProps: confirmProps, btnProps: confirmButton } = useViraPassword({
    matchWith: password,
    inputProps: { name: "confirm" },
  });
 
  return (
    <form action={action}>
      <label htmlFor="email">Email</label>
      <input
        id="email"
        name="email"
        type="email"
        autoComplete="username"
        defaultValue="hello@virastack.com"
      />
 
      <label htmlFor={inputProps.id}>New password</label>
      <div>
        <input {...inputProps} />
        <button {...btnProps} />
      </div>
 
      <label htmlFor={confirmProps.id}>Confirm password</label>
      <div>
        <input {...confirmProps} />
        <button {...confirmButton} />
      </div>
 
      <button type="submit" disabled={pending}>
        Create account
      </button>
 
      {state?.ok && <p>The server accepted the password.</p>}
      {state && !state.ok && (
        <ul role="alert">
          {state.issues.map((issue) => (
            <li key={issue}>{passwordMessages[issue]}</li>
          ))}
        </ul>
      )}
    </form>
  );
}
// app/signup/actions.ts
"use server";
 
import { validatePassword } from "@virastack/password/server";
import type { PasswordIssue } from "@virastack/password/strength";
 
import { policy } from "@/lib/password-policy";
 
export type SignupState = { ok: boolean; issues: PasswordIssue[] } | null;
 
export async function signup(_state: SignupState, formData: FormData): Promise<SignupState> {
  // The browser can be skipped; the server checks again with the same policy.
  const result = validatePassword(formData.get("password"), policy, {
    forbidden: [formData.get("email")],
    confirm: formData.get("confirm"),
  });
  if (!result.valid) return { ok: false, issues: result.issues };
 
  // await createUser(email, await hash(result.password)) — result.password is NFKC-normalized
  return { ok: true, issues: [] };
}
// app/api/password/route.ts
import { validatePassword } from "@virastack/password/server"
import { policy } from "@/lib/password-policy"
 
export async function POST(request: Request) {
  const { password, email } = await request.json()
  const result = validatePassword(password, policy, { forbidden: [email] })
  return Response.json({ valid: result.valid, issues: result.issues })
}

Neyi hash'lemeli

result.password değerini hash'leyin: NFKC ile normalleştirilmiştir; başka klavyede yazılan aynı parola girişte de doğrulanır. Giriş formundaki parolayı da normalizePassword ile aynı şekilde normalleştirin.

SSR ve Next.js

  • Yalnızca @virastack/password içinde "use client" vardır. Server Component, Server Action ve route handler'lar /server veya /strength import eder.
  • Politikayı "use client" içermeyen ortak bir dosyada tutun.
  • Hook sunucuda ve istemcide aynı işaretlemeyi üretir (id'ler useId'den gelir); hydration uyuşmazlığı olmaz.
  • Next.js ile next dev ve next start modlarında test edildi.
ÖncekiÖzelleştirmeSonrakiSızmış parolalar

Bu sayfada

  • Sunucu girişi
  • Server Action
  • Neyi hash'lemeli
  • SSR ve Next.js
Hata mı var? Düzeltin