Angular无法获取Django返回的JWT令牌,请求出现403错误
问题分析与解决方案
你的核心问题是跨域场景下Cookie未正确传递导致403错误,以及Angular 17 SSR环境下localStorage的使用限制,以下是针对性解决步骤:
一、解决跨域Cookie未传递的403问题
1. 修正Django登录接口的Cookie设置
你的UserView依赖从Cookie获取jwt,但登录接口需确保Cookie配置支持跨域传递。修改登录视图(LoginView)的响应代码:
# LoginView中返回响应的部分 response = Response({'message': 'Login success'}) response.set_cookie( key='jwt', value=generated_token, # 你的JWT生成结果 httponly=True, # 防XSS攻击,建议开启 secure=False, # 开发环境用False,生产HTTPS环境改为True samesite='Lax', # 关键:跨域场景不能用Strict,生产HTTPS可设为None max_age=3600*24, # Cookie有效期,按需调整 path='/' # 确保全站接口可访问该Cookie ) return response
Postman能正常请求是因为它不严格遵循浏览器的SameSite规则,而浏览器会拦截
SameSite=Strict的跨域Cookie。
2. 清理Django CORS配置冲突
你的settings.py中CORS_ORIGIN_WHITELIST与CORS_ORIGIN_ALLOW_ALL冲突,保留白名单更安全,同时补全中间件顺序:
# 移除 CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = [ 'http://localhost:4200', ] CORS_ALLOW_CREDENTIALS = True # 确保中间件顺序正确 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 补全此中间件 # 其他原有中间件... ]
3. 确保Angular所有请求携带Credentials
登录请求必须添加{withCredentials: true},否则浏览器不会存储服务器返回的Cookie:
// Angular登录请求示例 login(credentials: {username: string, password: string}) { this.http.post( 'http://localhost:8000/api/login/', credentials, {withCredentials: true} // 必须添加 ).subscribe(res => { console.log('登录成功'); }); }
你首页的请求已添加该配置,保持即可。
二、解决Angular 17中localStorage未定义的错误
Angular 17默认启用SSR(服务端渲染),服务端环境不存在浏览器专属的localStorage,需做环境判断:
import { Component, OnInit, PLATFORM_ID, Inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-home', templateUrl: './home.component.html' }) export class HomeComponent implements OnInit { message = ''; constructor( private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object // 注入平台标识 ) {} ngOnInit(): void { // 仅在浏览器环境使用localStorage if (isPlatformBrowser(this.platformId)) { const token = localStorage.getItem('jwt'); console.log(token); } this.http.get('http://localhost:8000/api/users/', {withCredentials: true}).subscribe( (res: any) => { this.message = `Hi ${res.name}`; }, err => { this.message = 'You are not logged in'; } ); } }
如果不需要SSR,可直接在angular.json中禁用:
// angular.json -> projects -> 你的项目 -> architect -> build -> options "ssr": false
三、验证步骤
- 重启Django和Angular服务
- 登录后,打开浏览器开发者工具的Application -> Cookies -> http://localhost:8000,确认
jwtCookie存在 - 刷新首页,查看Django控制台的
print(token)输出,应能正常获取令牌,403错误消失
内容的提问来源于stack exchange,提问作者art
相关产品推荐
相关产品推荐

