JWT and Guid Token - Portfolio

Menu
Przejdź do treści
Ten skrypt w React tworzy komponent, który automatycznie pobiera listę użytkowników z serwera, a następnie wyświetla ją w formie tabeli. Komponent obsługuje różne stany, takie jak ładowanie danych, wyświetlanie błędów oraz wyświetlanie danych po ich załadowaniu.
Szczegółowy opis działania skryptu:
  1. Inicjalizacja stanu komponentu:
    • users: Przechowuje listę użytkowników. Początkowo jest to pusta tablica.
    • loading: Wskazuje, czy dane są w trakcie ładowania. Początkowo ustawione na true.
    • error: Przechowuje ewentualne błędy, które mogą wystąpić podczas pobierania danych. Początkowo jest null.
  2. Pobieranie danych z serwera:
    • useEffect: Po pierwszym załadowaniu komponentu wywołuje asynchroniczną funkcję fetchUsers, która pobiera dane użytkowników z podanego adresu API.
    • Żądanie HTTP: Wysyłane jest zapytanie GET do serwera w celu pobrania listy użytkowników. Zapytanie zawiera nagłówki, takie jak Authorization z tokenem uwierzytelniającym oraz Content-Type jako application/json.
    • Obsługa odpowiedzi: Jeśli serwer zwróci poprawną odpowiedź, dane użytkowników są zapisywane w stanie users, a loading jest ustawione na false. Jeśli wystąpi błąd, jest on przechwytywany, a jego szczegóły są zapisane w stanie error.
  3. Renderowanie komponentu:
    • Ładowanie: Jeśli dane są w trakcie pobierania, wyświetlany jest komunikat "Loading...".
    • Błąd: Jeśli wystąpił błąd podczas pobierania danych, wyświetlany jest komunikat o błędzie.
    • Tabela z użytkownikami: Jeśli dane zostały poprawnie załadowane, komponent renderuje tabelę, w której wyświetla listę użytkowników. Każdy wiersz tabeli zawiera informacje o ID użytkownika, nazwie użytkownika, adresie e-mail, tokenie oraz dacie wygaśnięcia tokena.
import { useState, useEffect } from "react";

function UserList() {
 const [users, setUsers] = useState([]);
 const [loading, setLoading] = useState(true);
 const [error, setError] = useState(null);

 useEffect(() => {
   // Funkcja do pobierania użytkowników
   const fetchUsers = async () => {
     try {
       const response = await fetch("https://localhost:7106/api/admin/users", {
         method: "GET",
         headers: {
           Authorization: "FBEE68BE-C5FD-465A-89B8-AB04A81C5C78", // Podaj swój rzeczywisty token bez "Bearer"
           "Content-Type": "application/json",
         },
       });

       if (!response.ok) {
         throw new Error("Network response was not ok");
       }

       const data = await response.json();
       setUsers(data);
       setLoading(false);
     } catch (error) {
       setError(error);
       setLoading(false);
     }
   };

   fetchUsers();
 }, []);

 if (loading) {
   return <div className="text-center mt-5">Loading...</div>;
 }

 if (error) {
   return (
     <div className="text-center mt-5 text-danger">Error: {error.message}</div>
   );
 }

 return (
   <div className="container mt-5">
     <h2>User List</h2>
     <table
       className="table table-striped table-bordered"
       style={{ border: "1px solid black" }}
     >
       <thead>
         <tr>
           <th>ID</th>
           <th>Username</th>
           <th>Email</th>
           <th>Token</th>
           <th>Expiration Date</th>
         </tr>
       </thead>
       <tbody>
         {users.map((user) => (
           <tr key={user.id}>
             <td style={{ border: "1px solid black" }}>{user.id}</td>
             <td style={{ border: "1px solid black" }}>{user.userName}</td>
             <td style={{ border: "1px solid black" }}>{user.email}</td>
             <td style={{ border: "1px solid black" }}>{user.token}</td>
             <td style={{ border: "1px solid black" }}>
               {user.expirationDate}
             </td>
           </tr>
         ))}
       </tbody>
     </table>
   </div>
 );
}

export default UserList;

Ten skrypt tworzy formularz logowania w React, który umożliwia użytkownikowi zalogowanie się poprzez podanie adresu e-mail i hasła.
Co robi skrypt:
  1. Przechowywanie danych logowania: Skrypt zarządza stanami dla adresu e-mail, hasła, tokena JWT, informacji o błędzie oraz statusu ładowania.
  2. Obsługa logowania: Gdy użytkownik wypełni formularz i go wyśle, skrypt wysyła zapytanie HTTP POST do określonego API z danymi logowania. Skrypt oczekuje na odpowiedź serwera.
  3. Przechwytywanie tokena JWT: Po udanym logowaniu serwer zwraca token JWT. Skrypt zapisuje ten token w localStorage oraz w stanie komponentu.
  4. Dekodowanie tokena: Skrypt dekoduje token JWT, aby wyciągnąć z niego specyficzne informacje, takie jak UserToken, i zapisuje je w stanie komponentu.
  5. Wyświetlanie komunikatów:
    • Jeśli logowanie jest w toku, wyświetlany jest komunikat o ładowaniu.
    • Jeśli logowanie się nie powiedzie, wyświetlany jest komunikat o błędzie.
    • Po udanym logowaniu wyświetlany jest token JWT oraz wyciągnięta z niego informacja UserToken.
  6. Interfejs użytkownika: Formularz jest zbudowany z użyciem Bootstrap, co zapewnia responsywny i estetyczny wygląd. Po wprowadzeniu danych użytkownik klika przycisk "Zaloguj się", który jest dezaktywowany podczas ładowania.
import { useState } from "react";
import axios from "axios";
import { jwtDecode } from "jwt-decode"; // Poprawiony import

const Login = () => {
 const [email, setEmail] = useState("");
 const [password, setPassword] = useState("");
 const [token, setToken] = useState("");
 const [userToken, setUserToken] = useState(""); // Przechowywanie wartości UserToken
 const [error, setError] = useState("");
 const [loading, setLoading] = useState(false);

 const handleLogin = async (e) => {
   e.preventDefault();
   setError("");
   setLoading(true);
   setToken("");
   setUserToken("");

   try {
     const response = await axios.post(
       "https://localhost:7106/api/Users/login",
       {
         email,
         password,
       }
     );

     const { token } = response.data;
     localStorage.setItem("token", token); // Zapisz token w localStorage
     setToken(token); // Ustaw token w stanie komponentu
     const decoded = jwtDecode(token);
     console.log(decoded);
     // Dekodowanie JWT i wyciągnięcie UserToken
     const decodedToken = jwtDecode(token);
     setUserToken(decodedToken.UserToken); // Ustawienie UserToken w stanie komponentu

     setLoading(false);
   } catch {
     setLoading(false);
     setError("Nieprawidłowy email lub hasło.");
   }
 };

 return (
   <div className="container mt-5">
     <div className="row justify-content-center">
       <div className="col-md-6">
         <div className="card">
           <div className="card-body">
             <h4 className="card-title text-center">Logowanie</h4>
             {error && <div className="alert alert-danger">{error}</div>}
             {token && (
               <div className="alert alert-success">Token: {token}</div>
             )}
             {userToken && (
               <div className="alert alert-info">UserToken: {userToken}</div>
             )}
             <form onSubmit={handleLogin}>
               <div className="mb-3">
                 <label htmlFor="email" className="form-label">
                   Email
                 </label>
                 <input
                   type="email"
                   className="form-control"
                   id="email"
                   value={email}
                   onChange={(e) => setEmail(e.target.value)}
                   required
                 />
               </div>
               <div className="mb-3">
                 <label htmlFor="password" className="form-label">
                   Hasło
                 </label>
                 <input
                   type="password"
                   className="form-control"
                   id="password"
                   value={password}
                   onChange={(e) => setPassword(e.target.value)}
                   required
                 />
               </div>
               <button
                 type="submit"
                 className="btn btn-primary w-100"
                 disabled={loading}
               >
                 {loading ? "Logowanie..." : "Zaloguj się"}
               </button>
             </form>
           </div>
         </div>
       </div>
     </div>
   </div>
 );
};

export default Login;

Ten skrypt definiuje komponent React o nazwie Register, który tworzy formularz rejestracji użytkownika. Formularz pozwala użytkownikowi na wprowadzenie nazwy użytkownika, adresu e-mail oraz hasła, a następnie przesyła te dane do serwera w celu rejestracji.
Szczegółowe działanie skryptu:
  1. Inicjalizacja stanu komponentu:
    • userName: Przechowuje nazwę użytkownika wprowadzoną w formularzu.
    • password: Przechowuje hasło wprowadzone przez użytkownika.
    • email: Przechowuje adres e-mail wprowadzony przez użytkownika.
    • message: Przechowuje komunikat zwrotny po udanej rejestracji, np. "User registered successfully".
    • error: Przechowuje komunikat o błędzie, jeśli rejestracja się nie powiedzie.
    • loading: Wskazuje, czy proces rejestracji jest w toku.
  2. Obsługa zdarzenia rejestracji:
    • handleRegister: Funkcja, która jest wywoływana po przesłaniu formularza.
      • Najpierw resetuje komunikaty (message, error) i ustawia stan loading na true, co wskazuje na rozpoczęcie procesu rejestracji.
      • Wysyła zapytanie POST do API pod adresem https://localhost:7106/api/Users/register z danymi użytkownika (userName, password, email).
      • Jeśli rejestracja się powiedzie, ustawia komunikat sukcesu w stanie message i wyłącza loading.
      • Jeśli wystąpi błąd (np. serwer zwróci błąd lub zapytanie nie powiedzie się), zapisuje komunikat o błędzie w stanie error i wyłącza loading.
  3. Renderowanie formularza:
    • Formularz jest wyświetlany z trzema polami do wprowadzenia danych: nazwa użytkownika, adres e-mail i hasło.
    • Pod formularzem znajduje się przycisk „Zarejestruj się”, który jest dezaktywowany w trakcie procesu rejestracji (loading).
    • Jeśli proces rejestracji się powiedzie, wyświetlany jest komunikat o sukcesie. Jeśli wystąpi błąd, wyświetlany jest odpowiedni komunikat o błędzie.
  4. Stylizacja:
    • Komponent jest stylizowany przy użyciu Bootstrap. Formularz jest wyśrodkowany, a komunikaty sukcesu i błędu są wyświetlane w odpowiednich alertach (zielony dla sukcesu, czerwony dla błędu).
import { useState } from 'react';
import axios from 'axios';

const Register = () => {
   const [userName, setUserName] = useState('');
   const [password, setPassword] = useState('');
   const [email, setEmail] = useState('');
   const [message, setMessage] = useState('');
   const [error, setError] = useState('');
   const [loading, setLoading] = useState(false);

   const handleRegister = async (e) => {
       e.preventDefault();
       setMessage('');
       setError('');
       setLoading(true);

       try {
           const response = await axios.post('https://localhost:7106/api/Users/register', {
               userName,
               password,
               email
           });

           // Oczekiwany format odpowiedzi: { "message": "User registered successfully" }
           setMessage(response.data.message);
           setLoading(false);
       } catch (err) {
           setLoading(false);
           setError(err.response?.data?.message || 'Rejestracja nie powiodła się.');
       }
   };

   return (
       <div className="container mt-5">
           <div className="row justify-content-center">
               <div className="col-md-6">
                   <div className="card">
                       <div className="card-body">
                           <h4 className="card-title text-center">Rejestracja</h4>
                           {message && <div className="alert alert-success">{message}</div>}
                           {error && <div className="alert alert-danger">{error}</div>}
                           <form onSubmit={handleRegister}>
                               <div className="mb-3">
                                   <label htmlFor="userName" className="form-label">Nazwa użytkownika</label>
                                   <input
                                       type="text"
                                       className="form-control"
                                       id="userName"
                                       value={userName}
                                       onChange={(e) => setUserName(e.target.value)}
                                       required
                                   />
                               </div>
                               <div className="mb-3">
                                   <label htmlFor="email" className="form-label">Email</label>
                                   <input
                                       type="email"
                                       className="form-control"
                                       id="email"
                                       value={email}
                                       onChange={(e) => setEmail(e.target.value)}
                                       required
                                   />
                               </div>
                               <div className="mb-3">
                                   <label htmlFor="password" className="form-label">Hasło</label>
                                   <input
                                       type="password"
                                       className="form-control"
                                       id="password"
                                       value={password}
                                       onChange={(e) => setPassword(e.target.value)}
                                       required
                                   />
                               </div>
                               <button type="submit" className="btn btn-primary w-100" disabled={loading}>
                                   {loading ? 'Rejestracja...' : 'Zarejestruj się'}
                               </button>
                           </form>
                       </div>
                   </div>
               </div>
           </div>
       </div>
   );
};

export default Register;

Wróć do spisu treści