Angular中如何将Token存入LocalStorage并在所有API请求中携带Bearer Token
解决方案
1. 完善登录逻辑,将Token存入LocalStorage
首先修改authentication.service.ts,在登录成功时把Token存入LocalStorage,同时初始化时从LocalStorage恢复登录状态,避免页面刷新后状态丢失:
import { Injectable } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Observable, tap } from 'rxjs'; import { User } from './user.model'; import { environment } from '../environments/environment'; @Injectable({ providedIn: 'root' }) export class AuthenticationService { isLoggedIn = false; redirectUrl: string | null = null; constructor(private http: HttpClient) { // 初始化时从LocalStorage读取Token,恢复登录状态 const token = localStorage.getItem('authToken'); this.isLoggedIn = !!token; } login(): Observable<User> { const params = new HttpParams().append('param', 'value'); return this.http.get<User>(`${environment.apiUrl}azure${location.search}`, { params }).pipe( tap((user) => { this.isLoggedIn = true; // 将Token存入LocalStorage localStorage.setItem('authToken', user.token); }) ); } // 获取存储的Token getAuthToken(): string | null { return localStorage.getItem('authToken'); } // 登出方法 logout(): void { this.isLoggedIn = false; localStorage.removeItem('authToken'); } }
调整login.component.ts,移除冗余状态变量,直接依赖服务逻辑:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AuthenticationService } from '../services/authentication.service'; import { User } from '../models/user.model'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { user: User | undefined; constructor( private route: ActivatedRoute, private router: Router, private authService: AuthenticationService ) { } ngOnInit() { this.route.queryParamMap.subscribe((params) => { if (params.get('code')) { this.authService.login().subscribe({ next: (data) => { this.user = data; console.log('用户信息:', data); this.router.navigate(['/dashboard']); }, error: () => { console.log('登录失败'); this.router.navigate(['/login']); } }); } }); } }
2. 优化路由守卫,避免页面刷新后状态失效
修改auth.guard.ts,结合LocalStorage的Token判断登录状态:
import { CanActivateFn, Router } from '@angular/router'; import { inject } from '@angular/core'; import { AuthenticationService } from '../services/authentication.service'; export const authGuard: CanActivateFn = (route, state) => { const authService = inject(AuthenticationService); const router = inject(Router); // 优先从LocalStorage判断是否有有效Token const hasToken = !!authService.getAuthToken(); if (hasToken || authService.isLoggedIn) { return true; } else { return router.parseUrl('/login'); } };
3. 全局API请求自动携带Token(推荐使用HttpInterceptor)
创建拦截器自动给所有请求添加Token,无需在每个服务手动处理:
步骤1:创建AuthInterceptor
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable } from 'rxjs'; import { AuthenticationService } from './authentication.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthenticationService) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { const authToken = this.authService.getAuthToken(); // 如果有Token,克隆请求并添加Authorization头 if (authToken) { request = request.clone({ setHeaders: { Authorization: `Bearer ${authToken}` // 若后端要求直接传Token,改为 Authorization: authToken } }); } return next.handle(request); } }
步骤2:在AppModule中注册拦截器
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './services/auth.interceptor'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, AppRoutingModule, HttpClientModule], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule { }
之后customer.service.ts无需手动添加headers,请求会自动携带Token:
getSingleCustomerNotes(id: number): Observable<CustomerNotes> { return this.httpClient.get<CustomerNotes>(`${environment.apiUrl}customer/${id}/notes`); }
内容的提问来源于stack exchange,提问作者weinde
相关产品推荐
相关产品推荐

