You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  1. 调用 POST http://你的PHP后端域名/api/login,传入 email 和 password,获取返回的 Token
  2. 在受保护接口的请求头中添加 Authorization: Bearer <你的Token>
  3. 发送请求即可获取合法数据,和 Angular 端请求逻辑完全一致

关键注意事项

  • CORS 配置:PHP 后端必须设置正确的跨域头,允许 Angular 域名的请求
  • Token 安全:若用 LocalStorage,需做好 XSS 防护;若用 Cookie,必须开启 HttpOnly+Secure 属性
  • Token 过期处理:可在 Interceptor 中监听 401 错误,自动清除 Token 并跳转登录页
  • 前后端验证:前端表单验证仅提升体验,后端必须做二次验证,防止恶意请求

内容的提问来源于stack exchange,提问作者Sally

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:05:18