如何在Angular 14中通过Cookie保存登录凭证
后端(Laravel 8)调整
1. 修改登录控制器,把Token存入Cookie
你当前的登录逻辑用的是API Token,要实现免密登录,得把生成的Token放到HttpOnly Cookie里(这种Cookie前端读不到,能有效防XSS)。直接修改你的login方法:
public function login() { $this->request->validate([ 'email' => 'required|email', 'password' => 'required' ]); $user = User::where('email', $this->request->email)->first(); // 先清掉用户旧的token if ($user) { $user->tokens()->delete(); } if (! $user || ! Hash::check($this->request->password, $user->password)) { return R::SimpleError('The provided credentials are incorrect.'); } if($user->active == 1){ return R::SimpleError('Please contact support team!'); } $token = $user->createToken($this->request->email)->plainTextToken; $user->remember_token = $token; $user->save(); // 把Token存入Cookie,这里设置7天(168小时)有效期,也可以用forever()设永久 $response = R::Success($token, $user); return $response->withCookie( cookie('auth_token', $token, 168, null, null, env('APP_ENV') === 'production', true) ); // 参数说明:最后两个,第一个是secure(生产环境开HTTPS必须设true),第二个是HttpOnly(必须true,前端读不到) }
2. 新增中间件,用Cookie自动验证登录
Laravel API默认不处理Cookie,所以要写个中间件,让后端能从Cookie里拿Token验证用户:
先创建中间件:
php artisan make:middleware AuthenticateWithCookie
打开app/Http/Middleware/AuthenticateWithCookie.php,写入验证逻辑:
public function handle(Request $request, Closure $next) { $token = $request->cookie('auth_token'); if ($token) { // 解析Laravel plainTextToken的格式(用户ID|随机字符串) [$userId, $tokenValue] = explode('|', $token, 2); $user = User::find($userId); // 验证Token和数据库里的remember_token是否一致 if ($user && hash_equals($user->remember_token, $tokenValue)) { Auth::login($user); } } return $next($request); }
在app/Http/Kernel.php的$routeMiddleware里注册这个中间件:
'auth.cookie' => \App\Http\Middleware\AuthenticateWithCookie::class,
之后在routes/api.php里,给需要登录才能访问的路由添加该中间件:
Route::group(['middleware' => 'auth.cookie'], function () { // 示例:用户信息接口 Route::get('/user', function (Request $request) { return $request->user(); }); // 其他需要登录的接口都放这里 });
前端(Angular 14)处理
1. 登录请求开启Cookie保存
Angular的HttpClient默认不会自动保存Cookie,所以登录请求要加withCredentials: true,让浏览器自动存储服务器返回的Cookie:
// auth.service.ts import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { constructor(private http: HttpClient) {} login(email: string, password: string) { return this.http.post('/api/login', { email, password }, { withCredentials: true }); } // 验证当前是否处于登录状态的接口 checkAuth() { return this.http.get('/api/user', { withCredentials: true }); } }
2. 全局拦截器,统一携带Cookie
每次请求都手动加withCredentials太麻烦,写个拦截器统一处理所有API请求:
// auth.interceptor.ts import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler) { // 克隆请求并添加Cookie携带配置 const authReq = req.clone({ withCredentials: true }); return next.handle(authReq); } }
在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 {}
3. 页面初始化时自动验证登录状态
打开AppComponent,在页面加载时调用验证接口,Cookie有效的话自动登录,无需跳转登录页:
// app.component.ts import { AuthService } from './auth.service'; import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { constructor(private authService: AuthService, private router: Router) {} ngOnInit() { this.authService.checkAuth().subscribe({ next: (user) => { // 把用户信息存入全局状态(比如用BehaviorSubject) console.log('自动登录成功', user); }, error: () => { // Cookie无效,跳转到登录页 this.router.navigate(['/login']); } }); } }
安全提醒
- 生产环境必须开启HTTPS,同时把Cookie的
secure参数设为true,避免Cookie明文传输 - Cookie要设置
SameSite: 'strict'或'lax',防范CSRF攻击(可在Laravel的config/session.php中调整) - 坚决保持HttpOnly为
true,禁止前端读取Cookie,降低XSS攻击风险
内容的提问来源于stack exchange,提问作者Team Thunder
相关产品推荐
相关产品推荐

