Jak wykonać uwierzytelnianie JWT za pomocą Angular 6 SPA?
Opublikowany: 2022-03-11Dzisiaj przyjrzymy się, jak łatwo jest zintegrować uwierzytelnianie za pomocą tokena internetowego JSON (JWT) z jednostronicową aplikacją Angular 6 (lub nowszą) (SPA). Zacznijmy od odrobiny tła.
Czym są tokeny internetowe JSON i dlaczego ich używać?
Najłatwiejszą i najbardziej zwięzłą odpowiedzią jest to, że są wygodne, kompaktowe i bezpieczne. Przyjrzyjmy się szczegółowo tym twierdzeniom:
- Wygodne : używanie JWT do uwierzytelniania na zapleczu po zalogowaniu wymaga ustawienia jednego nagłówka HTTP, zadania, które można łatwo zautomatyzować za pomocą funkcji lub podklasy, jak zobaczymy później.
- Compact : token to po prostu ciąg zakodowany w base64, zawierający kilka pól nagłówka i ładunek, jeśli jest to wymagane. Całkowity token JWT jest zwykle mniejszy niż 200 bajtów, nawet jeśli jest podpisany.
- Bezpieczne : Chociaż nie jest to wymagane, świetną funkcją zabezpieczeń JWT jest to, że tokeny można podpisywać za pomocą szyfrowania pary kluczy publicznych/prywatnych RSA lub szyfrowania HMAC przy użyciu wspólnego klucza tajnego. Zapewnia to pochodzenie i ważność tokena.
Wszystko to sprowadza się do tego, że masz bezpieczny i wydajny sposób na uwierzytelnianie użytkowników, a następnie weryfikację wywołań do punktów końcowych API bez konieczności analizowania jakichkolwiek struktur danych ani implementowania własnego szyfrowania.
Teoria aplikacji
Tak więc, mając trochę tła, możemy teraz zagłębić się w to, jak działałoby to w rzeczywistej aplikacji. W tym przykładzie założę, że mamy serwer Node.js, na którym znajduje się nasze API, i rozwijamy listę rzeczy do zrobienia SPA przy użyciu Angular 6. Popracujmy również z tą strukturą API:
-
/auth
→POST
(podaj nazwę użytkownika i hasło w celu uwierzytelnienia i odebrania tokena JWT) -
/todos
→GET
(zwraca użytkownikowi listę rzeczy do zrobienia) -
/todos/{id}
→GET
(zwraca określony element listy rzeczy do zrobienia) -
/users
→GET
(zwraca listę użytkowników)
Niedługo przejdziemy przez tworzenie tej prostej aplikacji, ale na razie skoncentrujmy się na interakcji w teorii. Mamy prostą stronę logowania, na której użytkownik może wprowadzić swoją nazwę użytkownika i hasło. Po przesłaniu formularza wysyła te informacje do punktu końcowego /auth
. Serwer węzła może następnie uwierzytelnić użytkownika w dowolny odpowiedni sposób (wyszukiwanie bazy danych, wysyłanie zapytań do innej usługi sieciowej itp.), ale ostatecznie punkt końcowy musi zwrócić token JWT.
JWT dla tego przykładu będzie zawierać kilka oświadczeń zastrzeżonych i kilka oświadczeń prywatnych . Oświadczenia zastrzeżone to po prostu zalecane przez JWT pary klucz-wartość powszechnie używane do uwierzytelniania, podczas gdy oświadczenia prywatne to pary klucz-wartość mające zastosowanie tylko do naszej aplikacji:
Zastrzeżone roszczenia
-
iss
: wystawca tego tokena. Zwykle nazwa FQDN serwera, ale może to być dowolna, o ile aplikacja kliencka wie, że tego oczekuje. -
exp
: data i godzina wygaśnięcia tego tokena. To jest w sekundach od północy 1 stycznia 1970 GMT (czasu uniksowego). -
nbf
: Nieważne przed datownikiem. Nie jest używany często, ale daje dolną granicę okna ważności. Taki sam format jakexp
.
Prywatne roszczenia
-
uid
: Identyfikator zalogowanego użytkownika. -
role
: rola przypisana zalogowanemu użytkownikowi.
Nasze informacje będą zakodowane w base64 i podpisane przy użyciu HMAC ze współdzielonym kluczem todo-app-super-shared-secret
. Poniżej znajduje się przykład tego, jak wygląda token JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b2RvYXBpIiwibmJmIjoxNDk4MTE3NjQyLCJleHAiOjE0OTgxMjEyNDIsInVpZCI6MSwicm9sZSI6ImFkbWluIn0.ZDz_1vcIlnZz64nSM28yA1s-4c_iw3Z2ZtP-SgcYRPQ
Ten ciąg to wszystko, czego potrzebujemy, aby upewnić się, że mamy poprawny login, aby wiedzieć, który użytkownik jest podłączony, a nawet wiedzieć, jaką rolę ma użytkownik.
Większość bibliotek i aplikacji kontynuuje przechowywanie tego tokena JWT w localStorage
lub sessionStorage
w celu łatwego wyszukiwania, ale jest to po prostu powszechna praktyka. To, co zrobisz z tokenem, zależy od Ciebie, o ile możesz go udostępnić na przyszłe wywołania API.
Teraz, gdy SPA chce wykonać wywołanie do dowolnego z chronionych punktów końcowych API, wystarczy wysłać token w nagłówku HTTP Authorization
.
Authorization: Bearer {JWT Token}
Uwaga : Po raz kolejny jest to po prostu powszechna praktyka. JWT nie zaleca żadnej konkretnej metody wysyłania się do serwera. Możesz również dołączyć go do adresu URL lub wysłać w pliku cookie.
Gdy serwer otrzyma token JWT, może go zdekodować, zapewnić spójność za pomocą wspólnego klucza HMAC i sprawdzić wygaśnięcie za pomocą pól exp
i nbf
. Mógłby również użyć pola iss
, aby upewnić się, że jest pierwotnym wystawcą tego tokena JWT.
Gdy serwer jest zadowolony z ważności tokena, można użyć informacji przechowywanych w tokenie JWT. Na przykład podany przez nas uid
daje nam identyfikator użytkownika zgłaszającego żądanie. W tym konkretnym przykładzie uwzględniliśmy również pole role
, które pozwala nam podejmować decyzje, czy użytkownik powinien mieć dostęp do określonego punktu końcowego, czy nie. (To, czy ufasz tym informacjom, czy raczej chcesz przeprowadzić wyszukiwanie w bazie danych, zależy od wymaganego poziomu bezpieczeństwa).
function getTodos(jwtString) { var token = JWTDecode(jwtstring); if( Date.now() < token.nbf*1000) { throw new Error('Token not yet valid'); } if( Date.now() > token.exp*1000) { throw new Error('Token has expired'); } if( token.iss != 'todoapi') { throw new Error('Token not issued here'); } var userID = token.uid; var todos = loadUserTodosFromDB(userID); return JSON.stringify(todos); }
Zbudujmy prostą aplikację do zrobienia
Aby kontynuować, musisz mieć zainstalowaną najnowszą wersję Node.js (6.x lub nowszą), npm (3.x lub nowszą) i angular-cli. Jeśli potrzebujesz zainstalować Node.js, który zawiera npm, postępuj zgodnie z instrukcjami tutaj. Następnie angular-cli
można zainstalować za pomocą npm
(lub yarn
, jeśli ją zainstalowałeś):
# installation using npm npm install -g @angular/cli # installation using yarn yarn global add @angular/cli
Nie będę wchodzić w szczegóły schematu Angular 6, którego użyjemy tutaj, ale w następnym kroku stworzyłem repozytorium Github do przechowywania małej aplikacji do zrobienia, aby zilustrować prostotę dodawania uwierzytelniania JWT do Twojej aplikacji. Po prostu sklonuj go, korzystając z:
git clone https://github.com/sschocke/angular-jwt-todo.git cd angular-jwt-todo git checkout pre-jwt
Polecenie git checkout pre-jwt
przełącza do nazwanej wersji, w której nie zaimplementowano JWT.
Wewnątrz powinny znajdować się dwa foldery zwane server
i client
. Serwer jest serwerem Node API, który będzie hostował nasze podstawowe API. Klientem jest nasza aplikacja Angular 6.
Serwer interfejsu API węzła
Aby rozpocząć, zainstaluj zależności i uruchom serwer API.
cd server # installation using npm npm install # or installation using yarn yarn node app.js
Powinno być możliwe skorzystanie z tych linków i uzyskanie reprezentacji danych w formacie JSON. Na razie, dopóki nie uzyskamy uwierzytelnienia, zakodowaliśmy na sztywno punkt końcowy /todos
, aby zwrócić zadania dla userID=1
:
- http://localhost:4000: Strona testowa, aby sprawdzić, czy serwer Node jest uruchomiony
- http://localhost:4000/api/users: Zwróć listę użytkowników w systemie
- http://localhost:4000/api/todos: Zwróć listę zadań dla
userID=1
Aplikacja Angular
Aby rozpocząć pracę z aplikacją kliencką, musimy również zainstalować zależności i uruchomić serwer deweloperski.
cd client # using npm npm install npm start # using yarn yarn yarn start
Uwaga : W zależności od szybkości linii pobranie wszystkich zależności może trochę potrwać.
Jeśli wszystko idzie dobrze, powinieneś zobaczyć coś takiego podczas przechodzenia do http://localhost:4200:
Dodawanie uwierzytelniania przez JWT
Aby dodać obsługę uwierzytelniania JWT, skorzystamy z kilku dostępnych standardowych bibliotek, które to uproszczą. Możesz oczywiście zrezygnować z tych udogodnień i zaimplementować wszystko samodzielnie, ale to wykracza poza nasz zakres tutaj.
Najpierw zainstalujmy bibliotekę po stronie klienta. Jest rozwijany i utrzymywany przez Auth0, czyli bibliotekę umożliwiającą dodanie do witryny uwierzytelniania opartego na chmurze. Korzystanie z samej biblioteki nie wymaga korzystania z ich usług.
cd client # installation using npm npm install @auth0/angular-jwt # installation using yarn yarn add @auth0/angular-jwt
Za chwilę przejdziemy do kodu, ale skoro już przy tym jesteśmy, skonfigurujmy również stronę serwera. Użyjemy bibliotek body-parser
, jsonwebtoken
i express-jwt
, aby sprawić, by Node zrozumiał treści i znaczniki JWT JSON POST.
cd server # installation using npm npm install body-parser jsonwebtoken express-jwt # installation using yarn yarn add body-parser jsonwebtoken express-jwt
Punkt końcowy API do uwierzytelniania
Po pierwsze, potrzebujemy sposobu na uwierzytelnienie użytkowników przed przekazaniem im tokena. W naszym prostym demo skonfigurujemy po prostu stały punkt końcowy uwierzytelniania z zakodowaną na stałe nazwą użytkownika i hasłem. Może to być tak proste lub tak złożone, jak wymaga tego Twoja aplikacja. Ważne jest, aby odesłać token JWT.
W server/app.js
dodaj wpis pod pozostałymi require
liniami w następujący sposób:
const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const expressJwt = require('express-jwt');
Oraz następujące:
app.use(bodyParser.json()); app.post('/api/auth', function(req, res) { const body = req.body; const user = USERS.find(user => user.username == body.username); if(!user || body.password != 'todo') return res.sendStatus(401); var token = jwt.sign({userID: user.id}, 'todo-app-super-shared-secret', {expiresIn: '2h'}); res.send({token}); });
Jest to głównie podstawowy kod JavaScript. Pobieramy treść JSON, która została przekazana do punktu końcowego /auth
, znajdujemy użytkownika pasującego do tej nazwy użytkownika, sprawdzamy, czy mamy użytkownika i pasujące hasło, i zwracamy błąd 401 Unauthorized
HTTP, jeśli nie.
Ważną częścią jest generowanie tokenów, które podzielimy na trzy parametry. Składnia sign
jest następująca: jwt.sign(payload, secretOrPrivateKey, [options, callback])
, gdzie:
-
payload
to literał obiektowy par klucz-wartość, które chcesz zakodować w swoim tokenie. Te informacje mogą następnie zostać odszyfrowane z tokena przez każdego, kto ma klucz deszyfrujący. W naszym przykładzieuser.id
tak, że gdy ponownie otrzymamy token na zapleczu do uwierzytelnienia, wiemy, z którym użytkownikiem mamy do czynienia. -
secretOrPrivateKey
to wspólny tajny klucz szyfrowania HMAC — dla uproszczenia tego używaliśmy w naszej aplikacji — albo prywatny klucz szyfrowania RSA/ECDSA. -
options
reprezentują różne opcje, które można przekazać do kodera w postaci par klucz-wartość. Zazwyczaj określamy przynajmniejexpiresIn
(staje się zastrzeżonym roszczeniemexp
) iissuer
(zastrzeżone roszczenieiss
), aby token nie był ważny na zawsze, a serwer może sprawdzić, czy faktycznie wystawił token pierwotnie. -
callback
to funkcja do wywołania po zakończeniu kodowania, jeśli ktoś chce asynchronicznie obsłużyć kodowanie tokena.
(Możesz również przeczytać więcej szczegółów na temat options
i sposobu korzystania z kryptografii klucza publicznego zamiast wspólnego tajnego klucza).
Integracja Angular 6 JWT
Sprawienie, by Angular 6 działał z naszym JWT, jest dość proste przy użyciu angular-jwt
. Po prostu dodaj następujące elementy do client/src/app/app.modules.ts
:
import { JwtModule } from '@auth0/angular-jwt'; // ... export function tokenGetter() { return localStorage.getItem('access_token'); } @NgModule({ // ... imports: [ BrowserModule, AppRoutingModule, HttpClientModule, FormsModule, // Add this import here JwtModule.forRoot({ config: { tokenGetter: tokenGetter, whitelistedDomains: ['localhost:4000'], blacklistedRoutes: ['localhost:4000/api/auth'] } }) ], // ... }
To w zasadzie wszystko, czego potrzeba. Oczywiście musimy dodać trochę więcej kodu, aby przeprowadzić wstępne uwierzytelnienie, ale biblioteka angular-jwt
zajmuje się wysyłaniem tokena wraz z każdym żądaniem HTTP.

- Funkcja
tokenGetter()
robi dokładnie to, co mówi, ale sposób jej implementacji zależy wyłącznie od Ciebie. Zdecydowaliśmy się zwrócić token, który zapisaliśmy wlocalStorage
. Oczywiście możesz podać dowolną inną metodę, o ile zwraca ona ciąg znaków zakodowany w tokenie sieciowym JSON . - Opcja
whiteListedDomains
istnieje, więc możesz ograniczyć domeny, do których wysyłany jest token JWT, więc publiczne interfejsy API również nie otrzymują Twojego tokena JWT. - Opcja
blackListedRoutes
umożliwia określenie określonych tras, które nie powinny otrzymywać tokenów JWT, nawet jeśli znajdują się w domenie umieszczonej na białej liście. Na przykład punkt końcowy uwierzytelniania nie musi go odbierać, ponieważ nie ma sensu: token ma zwykle wartość NULL, gdy mimo to jest wywoływany.
Sprawienie, by wszystko działało razem
W tym momencie mamy sposób na wygenerowanie tokena JWT dla danego użytkownika przy użyciu punktu końcowego /auth
w naszym API, a w Angularze mamy wykonane prace hydrauliczne, aby wysłać token JWT z każdym żądaniem HTTP. Świetnie, ale można zauważyć, że dla użytkownika absolutnie nic się nie zmieniło. I miałbyś rację. Nadal możemy przejść do każdej strony w naszej aplikacji i możemy wywołać dowolny punkt końcowy interfejsu API, nawet bez wysyłania tokenu JWT. Niedobrze!
Musimy zaktualizować naszą aplikację kliencką, aby martwić się o to, kto jest zalogowany, a także zaktualizować nasz interfejs API, aby wymagał tokena JWT. Zacznijmy.
Potrzebujemy nowego komponentu Angulara do logowania. Ze względu na zwięzłość postaraj się, aby było to jak najprostsze. Będziemy również potrzebować usługi, która obsłuży wszystkie nasze wymagania dotyczące uwierzytelniania, oraz Angular Guard do ochrony tras, które nie powinny być dostępne przed zalogowaniem. Zrobimy następujące czynności w kontekście aplikacji klienckiej.
cd client ng g component login --spec=false --inline-style ng g service auth --flat --spec=false ng g guard auth --flat --spec=false
Powinno to wygenerować cztery nowe pliki w folderze client
:
src/app/login/login.component.html src/app/login/login.component.ts src/app/auth.service.ts src/app/auth.guard.ts
Następnie musimy zapewnić usługę uwierzytelniania i ochronę dla naszej aplikacji. Zaktualizuj client/src/app/app.modules.ts
:
import { AuthService } from './auth.service'; import { AuthGuard } from './auth.guard'; // ... providers: [ TodoService, UserService, AuthService, AuthGuard ],
A następnie zaktualizuj routing w client/src/app/app-routing.modules.ts
, aby użyć strażnika uwierzytelniania i podać trasę dla komponentu logowania.
// ... import { LoginComponent } from './login/login.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: 'todos', component: TodoListComponent, canActivate: [AuthGuard] }, { path: 'users', component: UserListComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent}, // ...
Na koniec zaktualizuj client/src/app/auth.guard.ts
o następującą zawartość:
import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; @Injectable() export class AuthGuard implements CanActivate { constructor(private router: Router) { } canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { if (localStorage.getItem('access_token')) { return true; } this.router.navigate(['login']); return false; } }
W przypadku naszej aplikacji demonstracyjnej po prostu sprawdzamy, czy w pamięci lokalnej istnieje token JWT. W rzeczywistych aplikacjach możesz zdekodować token i sprawdzić jego ważność, wygaśnięcie itp. Na przykład możesz użyć do tego JwtHelperService.
W tym momencie nasza aplikacja Angular będzie teraz zawsze przekierowywać Cię do strony logowania, ponieważ nie mamy możliwości zalogowania się. Naprawmy to, zaczynając od usługi uwierzytelniania w client/src/app/auth.service.ts
:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class AuthService { constructor(private http: HttpClient) { } login(username: string, password: string): Observable<boolean> { return this.http.post<{token: string}>('/api/auth', {username: username, password: password}) .pipe( map(result => { localStorage.setItem('access_token', result.token); return true; }) ); } logout() { localStorage.removeItem('access_token'); } public get loggedIn(): boolean { return (localStorage.getItem('access_token') !== null); } }
Nasza usługa uwierzytelniania ma tylko dwie funkcje, login
i logout
:
-
login
POST
podaje podanąusername
ipassword
do naszego zaplecza i ustawiaaccess_token
wlocalStorage
, jeśli otrzyma go z powrotem. Dla uproszczenia nie ma tu obsługi błędów. -
logout
po prostu czyściaccess_token
zlocalStorage
, co wymaga pozyskania nowego tokena, zanim będzie można ponownie uzyskać dostęp do dalszych elementów. -
loggedIn
to właściwość logiczna, której możemy szybko użyć do określenia, czy użytkownik jest zalogowany, czy nie.
I na koniec składnik logowania. Nie mają one żadnego związku z faktyczną pracą z JWT, więc możesz swobodnie kopiować i wklejać do client/src/app/login/login.components.html
:
<h4 *ngIf="error">{{error}}</h4> <form (ngSubmit)="submit()"> <div class="form-group col-3"> <label for="username">Username</label> <input type="text" name="username" class="form-control" [(ngModel)]="username" /> </div> <div class="form-group col-3"> <label for="password">Password</label> <input type="password" name="password" class="form-control" [(ngModel)]="password" /> </div> <div class="form-group col-3"> <button class="btn btn-primary" type="submit">Login</button> </div> </form>
A client/src/app/login/login.components.ts
będą potrzebować:
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; import { Router } from '@angular/router'; import { first } from 'rxjs/operators'; @Component({ selector: 'app-login', templateUrl: './login.component.html' }) export class LoginComponent { public username: string; public password: string; public error: string; constructor(private auth: AuthService, private router: Router) { } public submit() { this.auth.login(this.username, this.password) .pipe(first()) .subscribe( result => this.router.navigate(['todos']), err => this.error = 'Could not authenticate' ); } }
Voila, nasz przykład logowania w Angular 6:
Na tym etapie powinniśmy być w stanie zalogować się (za pomocą jemma
, paul
lub sebastian
z hasłem todo
) i ponownie zobaczyć wszystkie ekrany. Ale nasza aplikacja pokazuje te same nagłówki nawigacyjne i nie ma możliwości wylogowania się niezależnie od aktualnego stanu. Naprawmy to, zanim przejdziemy do naprawy naszego API.
W client/src/app/app.component.ts
zamień cały plik na następujący:
import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from './auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(private auth: AuthService, private router: Router) { } logout() { this.auth.logout(); this.router.navigate(['login']); } }
A dla client/src/app/app.component.html
zastąp sekcję <nav>
następującą:
<nav class="nav nav-pills"> <a class="nav-link" routerLink="todos" routerLinkActive="active" *ngIf="auth.loggedIn">Todo List</a> <a class="nav-link" routerLink="users" routerLinkActive="active" *ngIf="auth.loggedIn">Users</a> <a class="nav-link" routerLink="login" routerLinkActive="active" *ngIf="!auth.loggedIn">Login</a> <a class="nav-link" (click)="logout()" href="#" *ngIf="auth.loggedIn">Logout</a> </nav>
Sprawiliśmy, że nasza nawigacja jest świadoma kontekstu, że powinna wyświetlać tylko niektóre elementy w zależności od tego, czy użytkownik jest zalogowany, czy nie. auth.loggedIn
można oczywiście używać wszędzie tam, gdzie można zaimportować usługę uwierzytelniania.
Zabezpieczenie API
Być może myślisz, że to jest świetne… wszystko wygląda wspaniale . Ale spróbuj zalogować się za pomocą wszystkich trzech różnych nazw użytkownika, a zauważysz coś: wszystkie zwracają tę samą listę rzeczy do zrobienia. Jeśli spojrzymy na nasz serwer API, zobaczymy, że każdy użytkownik ma w rzeczywistości własną listę pozycji, więc co słychać?
Pamiętaj, że kiedy zaczynaliśmy, zakodowaliśmy nasz punkt końcowy API /todos
, aby zawsze zwracał listę rzeczy do zrobienia dla userID=1
. Dzieje się tak, ponieważ nie mieliśmy żadnego sposobu, aby dowiedzieć się, kto jest aktualnie zalogowanym użytkownikiem.
Teraz to robimy, więc zobaczmy, jak łatwo jest zabezpieczyć nasze punkty końcowe i wykorzystać informacje zaszyfrowane w tokenie JWT do zapewnienia wymaganej tożsamości użytkownika. Początkowo dodaj tę jedną linię do pliku server/app.js
tuż pod ostatnim app.use()
:
app.use(expressJwt({secret: 'todo-app-super-shared-secret'}).unless({path: ['/api/auth']}));
Używamy oprogramowania pośredniczącego express-jwt
, mówimy mu, jaki jest wspólny sekret, i określamy tablicę ścieżek, dla których nie powinien wymagać tokena JWT. I to wszystko. Nie ma potrzeby dotykania każdego punktu końcowego, tworzenia instrukcji if
w całości lub czegokolwiek.
Wewnętrznie oprogramowanie pośredniczące przyjmuje kilka założeń. Na przykład zakłada, że nagłówek HTTP Authorization
jest zgodny ze wspólnym wzorcem JWT Bearer {token}
. (Biblioteka ma jednak wiele opcji dostosowywania sposobu działania, jeśli tak nie jest. Zobacz użycie express-jwt, aby uzyskać więcej informacji).
Naszym drugim celem jest wykorzystanie informacji zakodowanych w JWT, aby dowiedzieć się, kto wykonuje połączenie. Po raz kolejny z pomocą przychodzi express-jwt
. W ramach odczytywania tokena i jego weryfikacji ustawia zaszyfrowany ładunek, który wysłaliśmy w procesie podpisywania do zmiennej req.user
w Express. Następnie możemy go użyć, aby natychmiast uzyskać dostęp do dowolnej z przechowywanych przez nas zmiennych. W naszym przypadku ustawiamy identyfikator użytkownika równy identyfikatorowi uwierzytelnionego użytkownika i jako taki możemy go req.user.userID
userID
Zaktualizuj ponownie server/app.js
i zmień punkt końcowy /todos
na następujący:
res.send(getTodos(req.user.userID));
I to wszystko. Nasze API jest teraz zabezpieczone przed nieautoryzowanym dostępem i możemy bezpiecznie określić, kto jest naszym uwierzytelnionym użytkownikiem w dowolnym punkcie końcowym. Nasza aplikacja kliencka ma również prosty proces uwierzytelniania, a wszelkie napisane przez nas usługi HTTP, które wywołują nasz punkt końcowy API, będą automatycznie miały dołączony token uwierzytelniający.
Jeśli sklonowałeś repozytorium Github i po prostu chcesz zobaczyć efekt końcowy w akcji, możesz sprawdzić kod w jego ostatecznej formie, używając:
git checkout with-jwt
Mam nadzieję, że ten przewodnik okazał się cenny przy dodawaniu uwierzytelniania JWT do własnych aplikacji Angular. Dziękuje za przeczytanie!