Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:
Dzierżawy zewnętrzne (dowiedz się więcej)
Z tego samouczka dowiesz się, jak utworzyć jednostronicową aplikację platformy React, która zarejestruje użytkowników przy użyciu zestawu SDK języka JavaScript natywnego uwierzytelniania.
W tym samouczku nauczysz się następujących rzeczy:
- Utwórz projekt react Next.js.
- Dodaj do niego zestaw MSAL JS SDK.
- Dodaj składniki interfejsu użytkownika aplikacji.
- Skonfiguruj projekt, aby zarejestrować użytkowników.
Wymagania wstępne
- Wykonaj kroki opisane w przewodniku Szybki start: logowanie użytkowników w jednostronicowej aplikacji React przy użyciu natywnego zestawu SDK JavaScript do uwierzytelniania. W tym przewodniku Szybki start pokazano, jak uruchomić przykładowy kod React.
- Wykonaj kroki opisane w temacie Konfigurowanie serwera proxy CORS w celu zarządzania nagłówkami CORS na potrzeby uwierzytelniania natywnego.
- Visual Studio Code lub inny edytor kodu.
- Node.js.
- Jeśli chcesz zezwolić użytkownikom na rejestrację przy użyciu nazwy użytkownika (alias), włącz wbudowany atrybut użytkownika Username w przepływie użytkownika rejestracji. Aby uzyskać instrukcje, zobacz Włączanie nazwy użytkownika w zasadach identyfikatora logowania.
Tworzenie projektu React i instalowanie zależności
W wybranej lokalizacji na komputerze uruchom następujące polecenia, aby utworzyć nowy projekt React o nazwie reactspa, przejdź do folderu projektu, a następnie zainstaluj pakiety:
npx create-next-app@latest
cd reactspa
npm install
Po pomyślnym uruchomieniu poleceń należy mieć aplikację z następującą strukturą:
spasample/
└──node_modules/
└──...
└──public/
└──...
└──src/
└──app/
└──favicon.ico
└──globals.css
└──page.tsx
└──layout.tsx
└──postcss.config.mjs
└──package-lock.json
└──package.json
└──tsconfig.json
└──README.md
└──next-env.d.ts
└──next.config.ts
Dodawanie zestawu JAVAScript SDK do projektu
Aby użyć w aplikacji natywnego pakietu SDK uwierzytelniania dla języka JavaScript, użyj terminala i zainstaluj go za pomocą następującego polecenia:
npm install @azure/msal-browser
Możliwości uwierzytelniania natywnego są częścią azure-msal-browser biblioteki. Aby użyć natywnych funkcji uwierzytelniania, należy zaimportować z @azure/msal-browser/custom-auth. Przykład:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Dodawanie konfiguracji klienta
W tej sekcji zdefiniujesz konfigurację dla natywnej publicznej aplikacji klienckiej uwierzytelniania, aby umożliwić jej interakcję z interfejsem zestawu SDK. W tym celu utwórz plik o nazwie src/config/auth-config.ts, a następnie dodaj następujący kod:
export const customAuthConfig: CustomAuthConfiguration = {
customAuth: {
challengeTypes: ["password", "oob", "redirect"],
authApiProxyUrl: "http://localhost:3001/api",
},
auth: {
clientId: "Enter_the_Application_Id_Here",
authority: "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com",
redirectUri: "/",
postLogoutRedirectUri: "/",
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "sessionStorage",
},
system: {
loggerOptions: {
loggerCallback: (
level: LogLevel,
message: string,
containsPii: boolean
) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
}
},
},
},
};
W kodzie znajdź symbol zastępczy:
Enter_the_Application_Id_Herenastępnie zastąp go identyfikatorem aplikacji (klienta) aplikacji zarejestrowanej wcześniej.Enter_the_Tenant_Subdomain_Herenastępnie zastąp ją poddomeną dzierżawy w centrum administracyjnym firmy Microsoft Entra. Na przykład, jeśli podstawowa domena najemcy tocontoso.onmicrosoft.com, użyjcontoso. Jeśli nie masz nazwy najemcy, dowiedz się, jak sprawdzić szczegóły najemcy.
Tworzenie składników interfejsu użytkownika
Ta aplikacja zbiera szczegóły użytkownika, takie jak imię i nazwisko, nazwa użytkownika (e-mail), hasło i jednorazowy kod dostępu od użytkownika. Dlatego aplikacja musi mieć formularz zbierający te informacje.
Utwórz folder o nazwie src/app/sign-up w folderze src .
Utwórz plik sign-up/components/InitialForm.tsx , a następnie wklej kod z pliku sign-up/components/InitialForm.tsx. Ten składnik wyświetla formularz zbierający atrybuty rejestracji użytkownika.
Utwórz plik sign-up/components/CodeForm.tsx , a następnie wklej kod z pliku sign-up/components/CodeForm.tsx. Ten składnik wyświetla formularz, który zbiera jednorazowy kod dostępu wysyłany do użytkownika. Ten formularz jest wymagany dla poczty e-mail z hasłem lub pocztą e-mail z jednorazową metodą uwierzytelniania kodu dostępu.
Jeśli wybrana metoda uwierzytelniania to wiadomość e-mail z hasłem, utwórz plik sign-up/components/PasswordForm.tsx , a następnie wklej kod z pliku sign-up/components/PasswordForm.tsx. Ten składnik wyświetla formularz wejściowy hasła.
Obsługa interakcji z formularzem
W tej sekcji dodasz kod, który obsługuje interakcje formularza rejestracji, takie jak przesyłanie szczegółów rejestracji użytkownika lub jednorazowego kodu dostępu lub hasła.
Utwórz plik sign-up/page.tsx , aby obsłużyć logikę przepływu rejestracji. Zawartość tego pliku:
Zaimportuj niezbędne składniki i wyświetl odpowiedni formularz na podstawie stanu. Zobacz pełny przykład w pliku sign-up/page.tsx:
import { useEffect, useState } from "react"; import { customAuthConfig } from "../../config/auth-config"; import { styles } from "./styles/styles"; import { InitialFormWithPassword } from "./components/InitialFormWithPassword"; import { CustomAuthPublicClientApplication, ICustomAuthPublicClientApplication, SignUpCodeRequiredState, // Uncomment if your choice of authentication method is email with password // SignUpPasswordRequiredState, SignUpCompletedState, AuthFlowStateBase, } from "@azure/msal-browser/custom-auth"; import { SignUpResultPage } from "./components/SignUpResult"; import { CodeForm } from "./components/CodeForm"; import { PasswordForm } from "./components/PasswordForm"; export default function SignUpPassword() { const [authClient, setAuthClient] = useState<ICustomAuthPublicClientApplication | null>(null); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [jobTitle, setJobTitle] = useState(""); const [city, setCity] = useState(""); const [country, setCountry] = useState(""); const [email, setEmail] = useState(""); //Uncomment if your choice of authentication method is email with password //const [password, setPassword] = useState(""); const [code, setCode] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [signUpState, setSignUpState] = useState<AuthFlowStateBase | null>(null); const [loadingAccountStatus, setLoadingAccountStatus] = useState(true); const [isSignedIn, setSignInState] = useState(false); useEffect(() => { const initializeApp = async () => { const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance); }; initializeApp(); }, []); useEffect(() => { const checkAccount = async () => { if (!authClient) return; const accountResult = authClient.getCurrentAccount(); if (accountResult.isCompleted()) { setSignInState(true); } setLoadingAccountStatus(false); }; checkAccount(); }, [authClient]); const renderForm = () => { if (loadingAccountStatus) { return; } if (isSignedIn) { return ( <div style={styles.signed_in_msg}>Please sign out before processing the sign up.</div> ); } if (signUpState instanceof SignUpCodeRequiredState) { return ( <CodeForm onSubmit={handleCodeSubmit} code={code} setCode={setCode} loading={loading} /> ); } //Uncomment the following block of code if your choice of authentication method is email with password /* else if(signUpState instanceof SignUpPasswordRequiredState) { return <PasswordForm onSubmit={handlePasswordSubmit} password={password} setPassword={setPassword} loading={loading} />; } */ else if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage />; } else { return ( <InitialForm onSubmit={handleInitialSubmit} firstName={firstName} setFirstName={setFirstName} lastName={lastName} setLastName={setLastName} jobTitle={jobTitle} setJobTitle={setJobTitle} city={city} setCity={setCity} country={country} setCountry={setCountry} email={email} setEmail={setEmail} loading={loading} /> ); } } return ( <div style={styles.container}> <h2 style={styles.h2}>Sign Up</h2> {renderForm()} {error && <div style={styles.error}>{error}</div>} </div> ); }Ten kod tworzy również instancję natywnej publicznej aplikacji klienckiej do uwierzytelniania z użyciem konfiguracji klienta:
const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance);Aby obsłużyć przesyłanie początkowego formularza, użyj następującego fragmentu kodu. Zobacz pełny przykład na stronie sign-up/page.tsx , aby dowiedzieć się, gdzie umieścić fragment kodu:
const handleInitialSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (!authClient) return; const attributes: UserAccountAttributes = { displayName: `${firstName} ${lastName}`, givenName: firstName, surname: lastName, jobTitle: jobTitle, city: city, country: country, }; const result = await authClient.signUp({ username: email, attributes }); const state = result.state; if (result.isFailed()) { if (result.error?.isUserAlreadyExists()) { setError("An account with this email already exists"); } else if (result.error?.isInvalidUsername()) { setError("Invalid uername"); } else if (result.error?.isInvalidPassword()) { setError("Invalid password"); } else if (result.error?.isAttributesValidationFailed()) { setError("Invalid attributes"); } else if (result.error?.isMissingRequiredAttributes()) { setError("Missing required attributes"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while signing up"); } } else { setSignUpState(state); } setLoading(false); };Metoda instancji SDK,
signUp(), uruchamia proces rejestracji.Aby obsłużyć jednorazowe przesyłanie kodu dostępu, użyj następującego fragmentu kodu. Zobacz pełny przykład na stronie sign-up/page.tsx , aby dowiedzieć się, gdzie umieścić fragment kodu:
const handleCodeSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); try { if (signUpState instanceof SignUpCodeRequiredState) { const result = await signUpState.submitCode(code); if (result.error) { if (result.error.isInvalidCode()) { setError("Invalid verification code"); } else { setError("An error occurred while verifying the code"); } return; } if (result.state instanceof SignUpCompletedState) { setSignUpState(result.state); } } } catch (err) { setError("An unexpected error occurred"); console.error(err); } finally { setLoading(false); } };Aby obsłużyć przesyłanie haseł, użyj następującego fragmentu kodu. Przesyłanie hasła jest obsługiwane, jeśli wybrana metoda uwierzytelniania to wiadomość e-mail z hasłem. Zobacz pełny przykład na stronie sign-up/page.tsx , aby dowiedzieć się, gdzie umieścić fragment kodu:
const handlePasswordSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (signUpState instanceof SignUpPasswordRequiredState) { const result = await signUpState.submitPassword(password); const state = result.state; if (result.isFailed()) { if (result.error?.isInvalidPassword()) { setError("Invalid password"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while submitting the password"); } } else { setSignUpState(state); } } setLoading(false); };Użyj
signUpState instanceof SignUpCompletedState, aby oznaczyć, że użytkownik został zarejestrowany i proces został zakończony. Zobacz pełny przykład na stronie sign-up/page.tsx:if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage/>; }
Zbieranie nazwy użytkownika (aliasu) podczas rejestracji
Możesz zezwolić użytkownikom na rejestrację przy użyciu nazwy użytkownika (aliasu) oprócz poczty e-mail. Nazwa użytkownika (alias) to alternatywny identyfikator logowania, taki jak identyfikator klienta, numer konta lub inna wybrana wartość.
Podczas rejestracji nazwa użytkownika (adres e-mail) jest zawsze wymagana jako identyfikator podstawowy, a nazwa użytkownika (alias) nie zastępuje go. Domyślnie nazwa użytkownika (alias) jest opcjonalna, chociaż administrator może skonfigurować ją zgodnie z potrzebami. Aplikacja zawsze zbiera nazwę użytkownika (adres e-mail) i zbiera alias jako atrybut obok wiadomości e-mail. Podczas logowania użytkownik może następnie zalogować się przy użyciu nazwy użytkownika (adresu e-mail) lub nazwy użytkownika (aliasu). Aby dowiedzieć się, jak atrybut nazwy użytkownika jest skonfigurowany jako opcjonalny lub wymagany, zobacz Konfigurowanie typów danych wejściowych użytkownika i układu strony.
Aby zebrać nazwę użytkownika (alias) podczas rejestracji:
Upewnij się, że wbudowany atrybut użytkownika username jest włączony w przepływie użytkownika rejestracji. Aby uzyskać instrukcje, zobacz Włączanie nazwy użytkownika w zasadach identyfikatora logowania.
Dodaj stan
flatUsernamedo strony rejestracji, a następnie uwzględnij atrybutflatusernamew obiekcieUserAccountAttributes, który przekazujesz dosignUp():const [flatUsername, setFlatUsername] = useState(""); const attributes: UserAccountAttributes = { displayName: `${firstName} ${lastName}`, //... flatusername: flatUsername, };Dodaj dane wejściowe aliasu do pliku InitialForm.tsx , aby zebrać wartość nazwy użytkownika (aliasu):
<input type="text" placeholder="Username (alias)" value={flatUsername} onChange={(e) => setFlatUsername(e.target.value)} style={styles.input} />Obsługa błędów związanych z nazwą użytkownika (alias):
-
result.error?.isUserAlreadyExists()obejmuje zduplikowaną wiadomość e-mail lub zduplikowaną nazwę użytkownika (alias). Zaktualizuj odpowiednio wiadomość, na przykład Konto z tą nazwą e-mail lub nazwą użytkownika już istnieje. - Nieprawidłowa nazwa użytkownika (alias) jest wyświetlana za pośrednictwem
result.error?.isAttributesValidationFailed(), a nieresult.error?.isInvalidUsername(). Rozgałęź tę metodę, aby wyświetlić komunikat specyficzny dla użytkownika.
-
Obsługa błędów rejestracji
Podczas rejestracji nie wszystkie akcje kończą się powodzeniem. Na przykład użytkownik może próbować zarejestrować się przy użyciu już używanego adresu e-mail lub przesłać nieprawidłowy kod dostępu jednorazowego wiadomości e-mail. Upewnij się, że prawidłowo obsłużysz błędy, gdy:
Uruchom przepływ rejestracji w metodzie
signUp().Prześlij jednorazowy kod dostępu w metodzie
submitCode().Prześlij hasło w metodzie
submitPassword(). Ten błąd obsługujesz, jeśli wybrany sposób rejestracji wykorzystuje adres e-mail i hasło.
Jednym z błędów, które mogą wynikać z signUp() metody, jest result.error?.isRedirectRequired(). Ten scenariusz występuje, gdy uwierzytelnianie natywne nie jest wystarczające do ukończenia przepływu uwierzytelniania. Jeśli na przykład serwer autoryzacji wymaga możliwości, których klient nie może podać. Dowiedz się więcej o internetowym mechanizmie awaryjnym uwierzytelniania natywnego i o tym, jak obsługiwać internetowy mechanizm awaryjny w aplikacji React.
Opcjonalnie: automatyczne logowanie użytkowników po zarejestrowaniu
Po pomyślnym zarejestrowaniu użytkownika możesz bezpośrednio zalogować się do aplikacji bez inicjowania nowego przepływu logowania. W tym celu użyj następującego fragmentu kodu. Zobacz pełny przykład na stronie sign-up/page.tsx:
if (signUpState instanceof SignUpCompletedState) {
const result = await signUpState.signIn();
const state = result.state;
if (result.isFailed()) {
setError(result.error?.errorData?.errorDescription || "An error occurred during auto sign-in");
}
if (result.isCompleted()) {
setData(result.data);
setSignUpState(state);
}
}
Uruchamianie i testowanie aplikacji
Otwórz okno terminalu i przejdź do folderu głównego aplikacji:
cd reactspaAby uruchomić serwer proxy CORS, uruchom następujące polecenie w terminalu:
npm run corsAby uruchomić aplikację React, otwórz kolejne okno terminalu, a następnie uruchom następujące polecenie:
cd reactspa npm startOtwórz przeglądarkę internetową i przejdź pod adres
http://localhost:3000/sign-up. Zostanie wyświetlony formularz rejestracji.Aby utworzyć konto, wprowadź szczegóły, wybierz przycisk Kontynuuj , a następnie postępuj zgodnie z monitami.
Następnie możesz zaktualizować aplikację React, aby zalogować użytkownika lub zresetować hasło użytkownika.
Konfigurowanie elementu poweredByHeader na wartość false w next.config.js
Domyślnie nagłówek x-powered-by jest dołączany do odpowiedzi HTTP, aby wskazać, że aplikacja jest oparta na Next.js. Jednak ze względów bezpieczeństwa lub dostosowywania możesz usunąć lub zmodyfikować ten nagłówek:
const nextConfig: NextConfig = {
poweredByHeader: false,
/* other config options here */
};