Przejdź do treści

Produkcja

Ustawienia wyszukiwania, udostępniania i bezpieczeństwa, z którymi prfct przychodzi od razu — co robi każde z nich i jak je zachować, budując dalej.

Interfejs, którego nie da się znaleźć albo któremu nie można zaufać, nie jest skończony. Ta strona ma od początku ustawienia opisane poniżej, podobnie jak każda aplikacja zaczęta od jej repozytorium. Żadne z nich nie wymaga bazy danych ani zewnętrznej usługi: każde mieszka w pliku, który możesz przeczytać, zmienić albo skopiować. W istniejącym projekcie podstawowe zabezpieczenia zainstalujesz z rejestru (zobacz W innym projekcie poniżej); pomocnicze pliki metadanych wystarczy skopiować z repozytorium.

Wyszukiwarki

Metadane

Każda strona sama się opisuje: tytuł, opis, kanoniczny adres URL, wersje językowe (hreflang, razem z x-default) oraz karty Open Graph i Twitter, z których korzystają podglądy linków. pageMetadata() tworzy to wszystko z czterech wartości.

app/[locale]/pricing/page.tsx
import type { Metadata } from "next"

import { pageMetadata } from "@/lib/i18n/metadata"
import { getI18n } from "@/lib/i18n/server"

export async function generateMetadata(): Promise<Metadata> {
  const { locale, t } = await getI18n()
  return pageMetadata({
    path: "/pricing",
    locale,
    title: t.pricing.title,
    description: t.pricing.description,
  })
}

Mapa strony i robots

app/sitemap.ts wymienia każdą stronę w każdym języku, razem z odnośnikami do jej tłumaczeń. app/robots.ts kieruje roboty do mapy strony i trzyma punkty z danymi, takie jak indeks wyszukiwania, z dala od wyników. Strony dokumentacji i przykładowe aplikacje trafiają na listę automatycznie. Dodając własną trasę, dopisz jej ścieżkę do listy w tym pliku.

Karty do udostępniania

Każda strona ma własną kartę 1200 × 630, renderowaną podczas budowania z jej tytułu i opisu przez lib/og.tsx. Nie ma żadnej usługi graficznej do utrzymania ani niczego do projektowania ręcznie.

pageMetadata() kieruje każdą stronę do adresu /og z dopisaną jej własną ścieżką, a karty dokumentacji, przykładów i kreatora motywów już istnieją. Trasa, którą dodasz, potrzebuje własnej trasy karty: skopiuj app/[locale]/og/themes/route.tsx do odpowiedniego folderu, na przykład app/[locale]/og/pricing/route.tsx. Bez niej podgląd linku do strony nie ma obrazu.

Dane strukturalne

<JsonLd> zapisuje dane schema.org, z których wyszukiwarki tworzą rozszerzone wyniki. Strona główna opisuje witrynę i jej kod źródłowy, a strony dokumentacji opisują się jako TechArticle z BreadcrumbList. Komponent zamienia znak < na sekwencję ucieczki, więc żaden tekst w danych nie zamknie jego elementu script.

Nagłówki bezpieczeństwa

Każda odpowiedź niesie bazowy zestaw zabezpieczeń, ustawiony raz w lib/security.ts i stosowany w next.config.ts.

NagłówekPrzed czym chroni
Content-Security-PolicySkryptami, stylami, ramkami i żądaniami z pochodzeń, których nie zatwierdzono; wtyczkami; przejęciem <base>; formularzami wysyłanymi do innych witryn.
Strict-Transport-SecurityCofnięciem do zwykłego HTTP, przez dwa lata, w każdej subdomenie.
X-Content-Type-OptionsZgadywaniem typu pliku przez przeglądarkę i uruchamianiem go jako skryptu.
X-Frame-OptionsClickjackingiem: pokazywaniem twojej strony w ramce na cudzej witrynie.
Referrer-PolicyWyciekiem pełnych adresów URL, razem z parametrami, do innych witryn.
Cross-Origin-Opener-PolicySięganiem przez window.opener ze stron, które otwierasz.
Permissions-PolicyDostępem do kamery, mikrofonu, lokalizacji, płatności i USB, z których nic na stronie nie korzysta, oraz interfejsem Topics, którym sieci reklamowe profilują odwiedzających.

W innym projekcie

Ten zestaw jest elementem rejestru. Zainstaluj go w dowolnym projekcie Next.js, a potem zastosuj w next.config.ts:

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/security.json
next.config.ts
import type { NextConfig } from "next"

import { securityHeaders } from "./lib/security"

const nextConfig: NextConfig = {
  poweredByHeader: false,
  async headers() {
    return [{ source: "/:path*", headers: securityHeaders }]
  },
}

export default nextConfig

Przed wdrożeniem sprawdź Strict-Transport-Security: obejmuje każdą subdomenę przez dwa lata i zawiera preload, więc każda subdomena musi już działać po HTTPS.

Dopuszczanie usługi

Polityka to dane: jeden wpis na dyrektywę. Żeby skorzystać z usługi z innego pochodzenia, dopisz je do dyrektyw, których potrzebuje. Skrypt analityczny na przykład wczytuje skrypt i wysyła żądania:

lib/security.ts
export const contentSecurityPolicy: Record<string, string[]> = {
  // …
  "script-src": [
    "'self'",
    "'unsafe-inline'",
    ...(isDev ? ["'unsafe-eval'"] : []),
    "https://plausible.io",
  ],
  // …
  "connect-src": ["'self'", ...(isDev ? ["ws:"] : []), "https://plausible.io"],
}

Zostaw wpisy z isDev: działają tylko w next dev, gdzie React potrzebuje eval do odtworzenia stosów błędów, a hot reload swojego gniazda.

Gdy coś się nie wczytuje, otwórz konsolę przeglądarki: każde zablokowane żądanie jest tam zgłaszane razem z dyrektywą, która je zablokowała.

Ostrzejsze zasady dla skryptów

Strony statyczne powstają raz, więc nie mogą nieść nowego nonce przy każdym żądaniu. Dlatego polityka dopuszcza skrypty osadzone w stronie, którymi Next.js ją uruchamia; skrypty z innych pochodzeń pozostają zablokowane. Jeśli twoja aplikacja i tak renderuje każde żądanie, na przykład za logowaniem, przejdź na politykę z nonce w proxy.ts, tak jak opisuje to przewodnik Next.js.

Zgłaszanie podatności

/.well-known/security.txt (RFC 9116) mówi badaczom bezpieczeństwa, gdzie zgłosić problem. Data ważności odnawia się przy każdym wdrożeniu. Wskaż w polu Contact własny adres w app/.well-known/security.txt/route.ts.

Zanim wdrożysz

  • Ustaw NEXT_PUBLIC_SITE_URL na swoją domenę, żeby kanoniczne adresy URL, mapa strony, karty do udostępniania i polecenia instalacji na nią wskazywały.
  • Daj każdej nowej trasie generateMetadata, które wywołuje pageMetadata(), trasę karty w app/[locale]/og/ i wpis w app/sitemap.ts.
  • Trzymaj sekrety w zmiennych środowiskowych bez przedrostka NEXT_PUBLIC_ i odczytuj je tylko w kodzie serwerowym. Wszystko z tym przedrostkiem trafia do każdego odwiedzającego.
  • Sprawdzaj wszystkie dane wejściowe na serwerze, nawet jeśli formularz zrobił to już w przeglądarce.
  • Wyświetlaj to, co wpisują ludzie, jako tekst. dangerouslySetInnerHTML jest dla znaczników wygenerowanych przez twój własny kod, nigdy dla danych od użytkowników.
  • Sprawdź wdrożoną stronę: securityheaders.com ocenia nagłówki, a Rich Results Test Google'a czyta dane strukturalne.