Przesyłanie danych z jednego miejsca do drugiego? Dla własnego spokoju i ochrony użytkowników powinieneś zabezpieczyć go za pomocą JWT.
Podczas tworzenia aplikacji bardzo ważne jest, aby chronić poufne dane przed nieautoryzowanym dostępem. Wiele nowoczesnych aplikacji internetowych, mobilnych i chmurowych używa interfejsów API REST jako podstawowego środka komunikacji. W rezultacie kluczowe znaczenie ma projektowanie i rozwijanie interfejsów API zaplecza z bezpieczeństwem na czele.
Jedno skuteczne podejście do zabezpieczania interfejsu API REST obejmuje tokeny JSON Web Token (JWT). Te tokeny oferują solidny mechanizm uwierzytelniania i autoryzacji użytkowników, pomagając chronić chronione zasoby przed dostępem złośliwych aktorów.
Czym są tokeny sieciowe JSON?
Token internetowy JSON (JWT) to szeroko stosowany standard bezpieczeństwa. Zapewnia zwięzłą, samodzielną metodę bezpiecznego przesyłania danych między aplikacją kliencką a systemem zaplecza.
Interfejs API REST może używać tokenów JWT do bezpiecznego identyfikowania i uwierzytelniania użytkowników, gdy wysyłają oni żądania HTTP w celu uzyskania dostępu do chronionych zasobów.
Token internetowy JSON składa się z trzech odrębnych części: nagłówka, ładunku i podpisu. Koduje każdą część i łączy je za pomocą kropki (".").
Nagłówek opisuje algorytm kryptograficzny użyty do podpisania tokena, podczas gdy ładunek zawiera dane o użytkowniku i wszelkie dodatkowe metadane.
Wreszcie podpis, obliczony na podstawie nagłówka, ładunku i tajnego klucza, zapewnia integralność i autentyczność tokena.
Mając na uboczu podstawy tokenów JWT, zbudujmy interfejs API REST Node.js i zaimplementujmy tokeny JWT.
Skonfiguruj aplikację Express.js i bazę danych MongoDB
Tutaj dowiesz się, jak zbudować proste uwierzytelnienie REST API który obsługuje zarówno funkcję rejestracji, jak i logowania. Gdy proces logowania uwierzytelni użytkownika, powinien on mieć możliwość wysyłania żądań HTTP do chronionej trasy API.
Możesz znaleźć kod projektu w this Repozytorium GitHub.
Rozpocząć, utwórz serwer sieciowy Expressi zainstaluj te pakiety:
npm install cors dotenv byrpt mongoose cookie-parser crypto jsonwebtoken mongodb
Następny, utwórz bazę danych MongoDB Lub skonfiguruj klaster MongoDB w chmurze. Następnie skopiuj ciąg połączenia z bazą danych, utwórz plik .env plik w katalogu głównym i wklej parametry połączenia:
CONNECTION_STRING="ciąg połączenia"
Skonfiguruj połączenie z bazą danych
Stwórz nowy utils/db.js plik w katalogu głównym folderu projektu. W tym pliku dodaj następujący kod, aby ustanowić połączenie z bazą danych przy użyciu Mongoose.
konst mangusta = wymagać('mangusta');
konst połączDB = asynchroniczny () => {
próbować {
czekać na mongoose.connect (proces.env. CIĄG POŁĄCZENIA);
konsola.dziennik(„Połączono z MongoDB!”);
} złapać (błąd) {
konsola.błąd(„Błąd podczas łączenia z MongoDB:”, błąd);
}
};
moduł.eksport = połączDB;
Zdefiniuj model danych
Zdefiniuj prosty schemat danych użytkownika za pomocą Mongoose. W katalogu głównym utwórz nowy model/użytkownik.model.js plik i dodaj następujący kod.
konst mangusta = wymagać('mangusta');
konst schemat użytkownika = nowy mangusta. Schemat({
nazwa użytkownika: Strunowy,
hasło: {
typ: Strunowy,
wymagany: PRAWDA,
unikalny: PRAWDA,
},
});
konst Użytkownik = mangusta.model("Użytkownik", schemat użytkownika);
moduł.eksport = Użytkownik;
Zdefiniuj kontrolery dla tras API
Funkcje kontrolera będą zarządzać rejestracją i logowaniem; są istotną częścią tego przykładowego programu. W katalogu głównym utwórz plik controllers/userControllers.js plik i dodaj następujący kod:
- Zdefiniuj kontroler rejestracji użytkowników.
Ten fragment kodu miesza podane hasło za pomocą bcrypt, a następnie tworzy nowy rekord użytkownika w bazie danych, przechowując nazwę użytkownika i zaszyfrowane hasło. Jeśli rejestracja się powiedzie, wysyła odpowiedź z komunikatem o powodzeniu.konst Użytkownik = wymagać(„../modele/model.użytkownika”);
konst bcrypt = wymagać(„bszyfruj”);
konst { wygeneruj token } = wymagać(„../oprogramowanie pośrednie/uwierzytelnianie”);exports.registerUżytkownik = asynchroniczny (wymaganie, res) => {
konst { nazwa użytkownika, hasło } = req.body;próbować {
konst hash = czekać na bcrypt.hash (hasło, 10);
czekać na User.create({ nazwa użytkownika, hasło: hasz });
res.status(201).wysłać({ wiadomość: „Użytkownik zarejestrowany pomyślnie” });
} złapać (błąd) {
konsola.log (błąd);
res.status(500).wysłać({ wiadomość: 'Wystąpił błąd!! ' });
}
}; - Zdefiniuj kontroler logowania do zarządzania procesem logowania użytkownika:
Gdy użytkownik wysyła żądanie do /login trasie, powinni przekazać swoje dane uwierzytelniające w treści żądania. Następnie kod weryfikuje te poświadczenia i generuje token internetowy JSON. Token jest bezpiecznie przechowywany w pliku cookie z rozszerzeniem httpTylko flaga ustawiona na true. Uniemożliwia to JavaScriptowi dostęp do tokena po stronie klienta, chroniąc przed potencjalnymi atakami typu cross-site scripting (XSS).exports.loginUżytkownik = asynchroniczny (wymaganie, res) => {
konst { nazwa użytkownika, hasło } = req.body;próbować {
konst użytkownik = czekać na User.findOne({ nazwa użytkownika });
Jeśli (!użytkownik) {
powrót res.status(404).wysłać({ wiadomość: 'Użytkownik nie znaleziony' });
}konst dopasowanie hasła = czekać na bcrypt.compare (hasło, hasło.użytkownika);
Jeśli (!pasujące hasło) {
powrót res.status(401).wysłać({ wiadomość: 'Nieprawidłowe dane logowania' });
}konst ładunek = { identyfikator użytkownika: identyfikator użytkownika };
konst token = generujToken (ładunek);
res.cookie('znak', żeton, { httpTylko: PRAWDA });
res.status(200.json({ wiadomość: 'Logowanie zakończone sukcesem'});
} złapać (błąd) {
konsola.log (błąd);
res.status(500).wysłać({ wiadomość: 'Wystąpił błąd podczas logowania' });
}
}; - Na koniec zdefiniuj chronioną trasę:
Dzięki przechowywaniu tokenu JWT w pliku cookie kolejne żądania API wysyłane przez uwierzytelnionego użytkownika będą automatycznie zawierały token, umożliwiając serwerowi weryfikację i autoryzację żądań.exports.getUsers = asynchroniczny (wymaganie, res) => {
próbować {
konst użytkownicy = czekać na User.find({});
res.json (użytkownicy);
} złapać (błąd) {
konsola.log (błąd);
res.status(500).wysłać({ wiadomość: 'Wystąpił błąd!!' });
}
};
Utwórz oprogramowanie pośredniczące uwierzytelniania
Teraz, po zdefiniowaniu kontrolera logowania, który generuje token JWT po pomyślnym uwierzytelnieniu, zdefiniuj funkcje uwierzytelniania oprogramowania pośredniego, które będą generować i weryfikować token JWT.
W katalogu głównym utwórz nowy folder, oprogramowanie pośrednie. Wewnątrz tego folderu dodaj dwa pliki: auth.js I config.js.
Dodaj ten kod do config.js:
konst krypto = wymagać(„krypto”);
moduł.eksport = {
tajny klucz: crypto.randomBytes(32).toString('klątwa')
};
Ten kod generuje nowy losowy tajny klucz przy każdym uruchomieniu. Możesz następnie użyć tego tajnego klucza do podpisania i zweryfikowania autentyczności tokenów JWT. Po pomyślnym uwierzytelnieniu użytkownika wygeneruj i podpisz JWT za pomocą tajnego klucza. Serwer użyje następnie klucza do sprawdzenia, czy JWT jest ważny.
Dodaj następujący kod w auth.js który definiuje funkcje oprogramowania pośredniego, które generują i weryfikują JWT.
konst jwt = wymagać(„jsonwebtoken”);
konst { tajny klucz } = wymagać('./konfiguracja');konst wygeneruj token = (ładunek) => {
konst token = jwt.sign (ładunek, tajny klucz, { Wygasa za: „1h” });
powrót żeton;
};konst weryfikujToken = (req, res, następny) => {
konst token = req.cookies.token;Jeśli (!token) {
powrót res.status(401.json({ wiadomość: „Brak podanego tokena” });
}jwt.verify (token, tajny klucz, (błąd, zdekodowany) => {
Jeśli (błąd) {
powrót res.status(401.json({ wiadomość: 'Nieprawidłowy Token' });
}req.userId = dekodowany.userId;
Następny();
});
};
moduł.exports = { wygeneruj Token, zweryfikuj Token };
The wygeneruj Token Funkcja generuje token JWT, podpisując ładunek za pomocą tajnego klucza i ustawiając czas wygaśnięcia, podczas gdy weryfikujToken służy jako oprogramowanie pośredniczące do weryfikacji autentyczności i ważności dostarczonego tokena.
Zdefiniuj trasy API
Stwórz nowy trasy/użytkownikRoutes.js plik w katalogu głównym i dodaj następujący kod.
konst ekspres = wymagać('wyrazić');
konst router = ekspres. router();
konst kontrolery użytkowników = wymagać(„../kontrolery/kontrolery użytkownika”);
konst { weryfikujToken} = wymagać(„../oprogramowanie pośrednie/uwierzytelnianie”);
router.post('/api/register', userControllers.registerUser);
router.post('/api/logowanie', userControllers.loginUser);
router.get('/api/użytkownicy', weryfikujToken, userControllers.getUsers);
moduł.eksport = router;
Zaktualizuj punkt wejścia serwera
Zaktualizuj swój serwer.js plik z następującym kodem.
konst ekspres = wymagać('wyrazić');
konst kors = wymagać(„kors”);
konst aplikacja = ekspres();
konst port = 5000;
wymagać('dotenv'.config();
konst połączDB = wymagać('./narzędzia/db');
konst cookieParser = wymagać(„parser plików cookie”);połączDB();
app.use (express.json());
app.use (express.urlencoded({ rozszerzony: PRAWDA }));
app.use (cors());
app.use (cookieParser());
konst trasy użytkownika = wymagać(„./trasy/trasy użytkownika”);
aplikacja.użyć('/', trasy użytkownika);
app.listen (port, () => {
konsola.dziennik(`Serwer nasłuchuje o godz http://localhost:${port}`);
});
Aby przetestować REST API, uruchom serwer programistyczny i wyślij żądania API do zdefiniowanych punktów końcowych:
węzeł serwer.js
Zabezpieczanie interfejsów API REST Node.js
Zabezpieczanie interfejsów API REST Node.js wykracza poza samo użycie tokenów JWT, chociaż odgrywają one kluczową rolę w uwierzytelnianiu i autoryzacji, konieczne jest przyjęcie holistycznego podejścia do bezpieczeństwa w celu ochrony zaplecza systemy. Oprócz tokenów JWT należy również rozważyć wdrożenie protokołu HTTPS w celu szyfrowania komunikacji, sprawdzania poprawności i oczyszczania danych wejściowych oraz wielu innych.
Łącząc wiele środków bezpieczeństwa, możesz stworzyć solidne ramy bezpieczeństwa dla swojego Node.js REST API i zminimalizuj ryzyko nieautoryzowanego dostępu, naruszenia danych i innych zabezpieczeń groźby.