Аутентификация и авторизация являются ключевыми аспектами безопасности современных веб-приложений. В Angular их реализация требует понимания маршрутизации, сервисов, интерсепторов HTTP и работы с токенами.
Аутентификация — процесс подтверждения личности пользователя. Наиболее распространённый способ аутентификации в Angular — использование JSON Web Token (JWT).
Пример сервиса аутентификации:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private authUrl = 'https://api.example.com/auth';
private currentUserSubject = new BehaviorSubject<string | null>(null);
constructor(private http: HttpClient) {}
login(username: string, password: string): Observable<any> {
return this.http.post<any>(`${this.authUrl}/login`, { username, password })
.pipe(tap(response => {
localStorage.setItem('token', response.token);
this.currentUserSubject.next(username);
}));
}
logout(): void {
localStorage.removeItem('token');
this.currentUserSubject.next(null);
}
get token(): string | null {
return localStorage.getItem('token');
}
get currentUser(): Observable<string | null> {
return this.currentUserSubject.asObservable();
}
}
Ключевые моменты:
localStorage или
sessionStorage.BehaviorSubject для отслеживания текущего
состояния пользователя.login получает токен и сохраняет его для
дальнейшего использования.Авторизация определяет права доступа пользователя к ресурсам приложения. В Angular она реализуется с помощью Guard-ов.
Пример Guard-а для маршрутов:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.token) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
Основные принципы:
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard]
}
Для автоматической передачи токена в заголовках HTTP-запросов используется интерсептор.
Пример интерсептора:
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.authService.token;
if (token) {
const cloned = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`)
});
return next.handle(cloned);
}
return next.handle(req);
}
}
Регистрация интерсептора в модуле приложения:
import { HTTP_INTERCEPTORS } from '@angular/common/http';
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }
]
Для реализации сложной авторизации удобно хранить роли пользователя в токене или отдельном сервисе. Пример использования Guard-а с ролями:
canActivate(): boolean {
const userRole = this.authService.getUserRole();
if (userRole === 'admin') {
return true;
} else {
this.router.navigate(['/not-authorized']);
return false;
}
}
Практика:
Кроме маршрутов, авторизация может применяться к отдельным компонентам с помощью директив:
<ng-container *ngIf="authService.hasRole('admin')">
<button>Удалить пользователя</button>
</ng-container>
Необходимо централизованно обрабатывать ошибки, связанные с истекшими токенами или несанкционированным доступом:
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
this.http.get('/protected-resource')
.pipe(
catchError(err => {
if (err.status === 401) {
this.authService.logout();
this.router.navigate(['/login']);
}
return throwError(() => err);
})
);
Ключевые принципы:
Для надежной аутентификации и авторизации в Angular рекомендуется строить архитектуру на основе следующих элементов:
Эта схема обеспечивает модульность, масштабируемость и безопасное управление доступом в приложениях на Angular.