React Academy · Lekcja

Dostawca Credentials i niestandardowe logowanie

Uwierzytelnianie użytkowników względem bazy danych za pomocą dostawcy credentials i niestandardowego formularza logowania.

Lekcja 3 z 412 kroki

Dostawca Credentials i niestandardowe logowanie to bezpłatna lekcja React Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.

Kiedy używać Credentials Provider

Użyj Credentials Provider, gdy uwierzytelniasz użytkowników za pomocą własnej bazy danych (adres e-mail + hasło), a nie dostawcy OAuth. Wymaga to starannego obsługiwania haszowania haseł i kwestii bezpieczeństwa.

Definiowanie Credentials Provider

Dodaj Credentials do tablicy dostawców. Funkcja authorize otrzymuje przesłane dane logowania i zwraca obiekt użytkownika albo null.

import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';

export const { handlers, auth } = NextAuth({
  providers: [
    Credentials({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        const user = await db.user.findUnique({ where: { email: credentials.email as string } });
        if (!user) return null;
        const valid = await bcrypt.compare(credentials.password as string, user.passwordHash);
        if (!valid) return null;
        return { id: user.id, name: user.name, email: user.email };
      },
    }),
  ],
});

Niestandardowy formularz logowania

Zbuduj formularz logowania jako Client Component, który wywołuje signIn('credentials', { email, password }) z next-auth/react.

'use client';
import { signIn } from 'next-auth/react';

export function LoginForm() {
  const [error, setError] = useState('');

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    const result = await signIn('credentials', {
      email: form.get('email'),
      password: form.get('password'),
      redirect: false, // handle redirect manually
    });
    if (result?.error) setError('Invalid email or password');
    else router.push('/dashboard');
  }

  return (
    <form onSubmit={handleSubmit}>
      {error && <p className="error">{error}</p>}
      <input name="email" type="email" required />
      <input name="password" type="password" required />
      <button type="submit">Sign in</button>
    </form>
  );
}

redirect: false przy obsłudze błędów

Przekaż redirect: false do signIn(), aby otrzymać obiekt wyniku i obsłużyć błędy w komponencie zamiast przekierowywać użytkownika na stronę błędu.

const result = await signIn('credentials', { email, password, redirect: false });
if (result?.error) {
  // result.error is 'CredentialsSignin' for auth failures
  setError('Invalid email or password');
}

Walidacja Zod w authorize

Sprawdzaj poprawność danych logowania za pomocą Zod wewnątrz funkcji authorize, zanim odwołasz się do bazy danych.

import { z } from 'zod';

const schema = z.object({ email: z.string().email(), password: z.string().min(8) });

async authorize(credentials) {
  const parsed = schema.safeParse(credentials);
  if (!parsed.success) return null;
  const { email, password } = parsed.data;
  // ... db lookup
}

Strategia sesji dla danych logowania

Provider danych logowania wymaga strategii sesji JWT (adapter bazy danych nie jest potrzebny do obsługi sesji). Należy jawnie ustawić session: { strategy: 'jwt' }.

export const { handlers, auth } = NextAuth({
  session: { strategy: 'jwt' },
  providers: [Credentials({ ... })],
});

Dodawanie niestandardowych pól do sesji

Dodatkowe dane użytkownika należy przekazywać za pośrednictwem callbacków JWT i sesji, aby udostępnić je w useSession().

callbacks: {
  async jwt({ token, user }) {
    if (user) { token.id = user.id; token.role = user.role; }
    return token;
  },
  async session({ session, token }) {
    session.user.id = token.id as string;
    session.user.role = token.role as string;
    return session;
  },
},

Haszowanie haseł

Przed zapisaniem hasła należy zawsze haszować za pomocą bcrypt. Nigdy nie należy przechowywać haseł w postaci jawnego tekstu.

import bcrypt from 'bcryptjs';

// On registration:
const passwordHash = await bcrypt.hash(password, 12);
await db.user.create({ data: { email, passwordHash } });

// On login (in authorize):
const valid = await bcrypt.compare(submittedPassword, user.passwordHash);

Ograniczanie częstotliwości prób logowania

Należy chronić endpoint danych logowania przed atakami siłowymi, ograniczając częstotliwość prób logowania za pomocą middleware lub magazynu w pamięci.

// middleware.ts or in a rate-limiting library
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';

const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s') });

// Check in authorize before DB query:
const { success } = await ratelimit.limit(credentials.email as string);
if (!success) return null;

Proces rejestracji

Rejestracja jest oddzielona od Auth.js — użytkownika należy utworzyć w bazie danych (z hasłem poddanym haszowaniu) za pomocą Server Action lub trasy API, a następnie zalogować go za pomocą signIn('credentials', ...).

Szybkie sprawdzenie

Dlaczego podczas wywoływania signIn() w niestandardowym formularzu logowania należy przekazać redirect: false?

Podsumowanie

Provider danych logowania wywołuje funkcję authorize z przesłanymi danymi formularza. Należy przeprowadzić walidację za pomocą Zod, porównać hasła poddane haszowaniu za pomocą bcrypt i zwrócić obiekt użytkownika albo null. W formularzu należy użyć redirect: false, aby samodzielnie obsługiwać błędy, oraz zawsze stosować strategię JWT razem z danymi logowania.

Bezpłatny start

Ucz się React dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
88
Lekcje
324

Często zadawane pytania

Czy lekcja „Dostawca Credentials i niestandardowe logowanie” jest bezpłatna?

Tak — pełny tekst „Dostawca Credentials i niestandardowe logowanie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Dostawca Credentials i niestandardowe logowanie”?

Uwierzytelnianie użytkowników względem bazy danych za pomocą dostawcy credentials i niestandardowego formularza logowania. Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć React Academy?

Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Dostawca Credentials i niestandardowe logowanie”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?

Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Konfiguracja Auth.js w Next.js App Router
  2. Zarządzanie sesją i hook useSession
  3. Dostawca Credentials i niestandardowe logowanie
  4. Ochrona tras oparta na middleware
← Powrót do React Academy