Angular登录注册后带Bearer Token访问API的实现方案咨询
Angular 登录注册+API 访问完整实现方案
核心组件必要性说明
直接回答你关心的工具选型:
- Route Guards:必须用,用来拦截未登录用户访问受保护路由,自动跳转登录页
- HTTP Interceptor:必须用,自动给所有请求携带 Token,避免每次手动拼接请求头
- LocalStorage/Cookies:二选一,用来存储 Token。LocalStorage 实现简单但存在 XSS 风险;Cookies 若配置
HttpOnly+Secure属性更安全,且 Postman 可自动携带同域 Cookie - 以上组件配合使用,既能实现 Angular 端的安全访问,也支持 Postman 手动携带 Token 测试 API
一、Angular 端具体实现
1. 登录/注册组件(表单交互)
用 Reactive Forms 实现带验证的登录表单,示例代码:
// login.component.ts import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AuthService } from '../auth.service'; import { Router } from '@angular/router'; @Component({ selector: 'app-login', templateUrl: './login.component.html' }) export class LoginComponent { loginForm: FormGroup; constructor( private fb: FormBuilder, private authService: AuthService, private router: Router ) { this.loginForm = this.fb.group({ email: ['', [Validators.required, Validators.email]], password: ['', Validators.required] }); } onSubmit() { if (this.loginForm.valid) { this.authService.login(this.loginForm.value).subscribe({ next: (res) => { this.authService.setToken(res.token); this.router.navigate(['/dashboard']); }, error: (err) => { alert('登录失败:' + err.error.message); } }); } } }
注册组件逻辑类似,仅需调用 authService.register() 接口,后端处理注册成功后可自动登录或跳转登录页。
2. AuthService(核心服务)
封装登录、注册、Token 管理逻辑:
// auth.service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthService { private apiUrl = 'http://你的PHP后端域名/api'; private tokenKey = 'auth_token'; constructor(private http: HttpClient) {} login(credentials: { email: string; password: string }): Observable<any> { return this.http.post(`${this.apiUrl}/login`, credentials); } register(userData: { name: string; email: string; password: string }): Observable<any> { return this.http.post(`${this.apiUrl}/register`, userData); } setToken(token: string): void { // 用 LocalStorage 存储(简单易实现) localStorage.setItem(this.tokenKey, token); // 若用 Cookie,可使用 ngx-cookie-service 库 // this.cookieService.set(this.tokenKey, token, 7, '/', undefined, true, 'Strict'); } getToken(): string | null { return localStorage.getItem(this.tokenKey); // return this.cookieService.get(this.tokenKey); } logout(): void { localStorage.removeItem(this.tokenKey); // this.cookieService.delete(this.tokenKey); } isLoggedIn(): boolean { return !!this.getToken(); } }
3. HTTP Interceptor(自动携带 Token)
创建拦截器,给所有请求添加 Authorization 头:
// auth.interceptor.ts import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthService) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { const token = this.authService.getToken(); if (token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next.handle(request); } }
在 app.module.ts 中注册拦截器:
// app.module.ts import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }) export class AppModule {}
4. Route Guard(保护路由)
创建守卫,拦截未登录用户访问受保护页面:
// auth.guard.ts 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.isLoggedIn()) { return true; } // 跳转登录页并记录当前路由,登录后自动返回 this.router.navigate(['/login'], { queryParams: { returnUrl: window.location.pathname } }); return false; } }
在路由配置中应用守卫:
// app-routing.module.ts import { Routes } from '@angular/router'; import { LoginComponent } from './login/login.component'; import { RegisterComponent } from './register/register.component'; import { DashboardComponent } from './dashboard/dashboard.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'register', component: RegisterComponent }, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, { path: '', redirectTo: '/login', pathMatch: 'full' } ];
二、PHP 后端适配逻辑
1. 登录接口(生成 Token)
使用 Firebase JWT 库生成 Token(需先通过 Composer 安装 firebase/php-jwt):
// api/login.php <?php header("Access-Control-Allow-Origin: http://你的Angular域名"); header("Access-Control-Allow-Headers: Content-Type, Authorization"); header("Access-Control-Allow-Methods: POST"); require 'vendor/autoload.php'; use Firebase\JWT\JWT; use Firebase\JWT\Key; // 数据库连接逻辑(自行替换) $db = new PDO('mysql:host=localhost;dbname=你的数据库名', '用户名', '密码'); $data = json_decode(file_get_contents('php://input')); $email = $data->email; $password = $data->password; // 查询用户 $stmt = $db->prepare("SELECT * FROM users WHERE email = ?"); $stmt->execute([$email]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if ($user && password_verify($password, $user['password'])) { $secret_key = '你的JWT密钥(需和后端验证一致)'; $payload = array( "iat" => time(), "exp" => time() + 3600, // Token 1小时过期 "user_id" => $user['id'] ); $jwt = JWT::encode($payload, $secret_key, 'HS256'); echo json_encode(array("token" => $jwt)); } else { http_response_code(401); echo json_encode(array("message" => "用户名或密码错误")); } ?>
2. 受保护接口(验证 Token)
// api/user/profile.php <?php header("Access-Control-Allow-Origin: http://你的Angular域名"); header("Access-Control-Allow-Headers: Content-Type, Authorization"); header("Access-Control-Allow-Methods: GET"); require 'vendor/autoload.php'; use Firebase\JWT\JWT; use Firebase\JWT\Key; $secret_key = '你的JWT密钥'; $headers = getallheaders(); if (!isset($headers['Authorization'])) { http_response_code(401); echo json_encode(array("message" => "缺少Token")); exit; } $token = str_replace('Bearer ', '', $headers['Authorization']); try { $decoded = JWT::decode($token, new Key($secret_key, 'HS256')); // 根据解码后的用户ID查询数据 echo json_encode(array("user" => array("id" => $decoded->user_id, "email" => $user['email']))); } catch (Exception $e) { http_response_code(401); echo json_encode(array("message" => "无效Token")); } ?>
三、Postman 测试 API
- 调用
POST http://你的PHP后端域名/api/login,传入email和password,获取返回的 Token - 在受保护接口的请求头中添加
Authorization: Bearer <你的Token> - 发送请求即可获取合法数据,和 Angular 端请求逻辑完全一致
关键注意事项
- CORS 配置:PHP 后端必须设置正确的跨域头,允许 Angular 域名的请求
- Token 安全:若用 LocalStorage,需做好 XSS 防护;若用 Cookie,必须开启
HttpOnly+Secure属性 - Token 过期处理:可在 Interceptor 中监听 401 错误,自动清除 Token 并跳转登录页
- 前后端验证:前端表单验证仅提升体验,后端必须做二次验证,防止恶意请求
内容的提问来源于stack exchange,提问作者Sally
相关产品推荐
相关产品推荐

