Angular登录注册功能出现400错误求助
Angular 登录/注册首次正常,刷新后POST请求400错误排查
问题描述
我正在构建一款Angular应用,首次运行时登录与注册功能正常,但再次加载后,登录和注册的POST请求出现错误:Failed to load resource: the server responded with a status of 400 ()。已反复检查Firebase API密钥和授权域名,但问题仍未解决。
相关代码
auth.component.ts(登录页面TypeScript代码)
import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { Observable } from 'rxjs'; import { AuthResponseData, AuthService, } from '../../services/auth/auth.service'; @Component({ selector: 'app-auth', templateUrl: './auth.component.html', }) export class AuthComponent { isLoginMode = true; isLoading = false; error: string = null; constructor(private authService: AuthService, private router: Router) {} onSwitchMode() { this.isLoginMode = !this.isLoginMode; } onSubmit(form: NgForm) { if (!form.valid) { return; } const email = form.value.email; const password = form.value.password; let authObs: Observable<AuthResponseData>; this.isLoading = true; if (this.isLoginMode) { authObs = this.authService.login(email, password); } else { authObs = this.authService.signup(email, password); } authObs.subscribe( (resData) => { console.log(resData); this.isLoading = false; this.router.navigate(['/recipes']); }, (errorMessage) => { console.log(errorMessage); this.error = errorMessage; this.isLoading = false; } ); form.reset(); } }
auth.service.ts代码
import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Router } from '@angular/router'; import { catchError, tap } from 'rxjs/operators'; import { throwError, BehaviorSubject } from 'rxjs'; import { User } from '../../models/user.model'; export interface AuthResponseData { kind: string; idToken: string; email: string; refreshToken: string; expiresIn: string; localId: string; registered?: boolean; } @Injectable({ providedIn: 'root' }) export class AuthService { user = new BehaviorSubject<User>(null); private tokenExpirationTimer: any; constructor(private http: HttpClient, private router: Router) {} signup(email: string, password: string) { return this.http .post<AuthResponseData>( 'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=****', { email: email, password: password, returnSecureToken: true, } ) .pipe( catchError(this.handleError), tap((resData) => { this.handleAuthentication( resData.email, resData.localId, resData.idToken, +resData.expiresIn ); }) ); } login(email: string, password: string) { return this.http .post<AuthResponseData>( 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=****', { email: email, password: password, returnSecureToken: true, } ) .pipe( catchError(this.handleError), tap((resData) => { this.handleAuthentication( resData.email, resData.localId, resData.idToken, +resData.expiresIn ); }) ); } autoLogin() { const userData: { email: string; id: string; _token: string; _tokenExpirationDate: string; } = JSON.parse(localStorage.getItem('userData')); if (!userData) { return; } const loadedUser = new User( userData.email, userData.id, userData._token, new Date(userData._tokenExpirationDate) ); if (loadedUser.token) { this.user.next(loadedUser); const expirationDuration = new Date(userData._tokenExpirationDate).getTime() - new Date().getTime(); this.autoLogout(expirationDuration); } } logout() { this.user.next(null); this.router.navigate(['/auth']); localStorage.removeItem('userData'); if (this.tokenExpirationTimer) { clearTimeout(this.tokenExpirationTimer); } this.tokenExpirationTimer = null; } autoLogout(expirationDuration: number) { this.tokenExpirationTimer = setTimeout(() => { this.logout(); }, expirationDuration); } private handleAuthentication( email: string, userId: string, token: string, expiresIn: number ) { const expirationDate = new Date(new Date().getTime() + expiresIn * 1000); const user = new User(email, userId, token, expirationDate); this.user.next(user); this.autoLogout(expiresIn * 1000); localStorage.setItem('userData', JSON.stringify(user)); } private handleError(errorRes: HttpErrorResponse) { let errorMessage = 'An unknown error occurred!'; if (!errorRes.error || !errorRes.error.error) { return throwError(errorMessage); } switch (errorRes.error.error.message) { case 'EMAIL_EXISTS': errorMessage = 'This email exists already'; break; case 'EMAIL_NOT_FOUND': errorMessage = 'This email does not exist.'; break; case 'INVALID_PASSWORD': errorMessage = 'This password is not correct.'; break; } return throwError(errorMessage); } }
排查方向建议
- 检查localStorage用户数据:刷新后
autoLogin会读取userData,可在控制台执行localStorage.getItem('userData'),确认token是否过期、数据格式是否正常。 - 确认Firebase API密钥有效性:代码中
****需替换为真实有效且权限正常的Firebase Web API密钥,检查密钥是否过期或被限制。 - 对比请求参数与头信息:在开发者工具Network面板,查看400请求的Payload和Headers,与首次正常请求对比,确认email、password等参数格式是否一致。
- 检查Firebase Auth配置:登录Firebase控制台,确认邮箱/密码登录方式已开启,无异常账号限制。
- 补充token续期逻辑:当前代码未实现refreshToken刷新机制,token过期后后续请求会失败,需添加利用refreshToken获取新token的逻辑。
内容的提问来源于stack exchange,提问作者ADITYA CHAKRABORTY
相关产品推荐
相关产品推荐

